package utilities

import (
	
)

// DoubleArray is a Double Array implementation of trie on sequences of strings.
type DoubleArray struct {
	// Encoding keeps an encoding from string to int
	Encoding map[string]int
	// Base is the base array of Double Array
	Base []int
	// Check is the check array of Double Array
	Check []int
}

// NewDoubleArray builds a DoubleArray from a set of sequences of strings.
func ( [][]string) *DoubleArray {
	 := &DoubleArray{Encoding: make(map[string]int)}
	if len() == 0 {
		return 
	}

	 := registerTokens(, )
	sort.Sort(byLex())

	 := node{row: -1, col: -1, left: 0, right: len()}
	addSeqs(, , 0, )

	for  := len(.Base);  > 0; -- {
		if .Check[-1] != 0 {
			.Base = .Base[:]
			.Check = .Check[:]
			break
		}
	}
	return 
}

func registerTokens( *DoubleArray,  [][]string) [][]int {
	var  [][]int
	for ,  := range  {
		 := make([]int, 0, len())
		for ,  := range  {
			if ,  := .Encoding[]; ! {
				.Encoding[] = len(.Encoding)
			}
			 = append(, .Encoding[])
		}
		 = append(, )
	}
	for  := range  {
		[] = append([], len(.Encoding))
	}
	return 
}

type node struct {
	row, col    int
	left, right int
}

func ( node) ( [][]int) int {
	return [.row][.col]
}

func ( node) ( [][]int) []*node {
	var  []*node
	 := int(-1)
	 := new(node)
	for  := .left;  < .right; ++ {
		if  == [][.col+1] {
			continue
		}
		.right = 
		 = &node{
			row:  ,
			col:  .col + 1,
			left: ,
		}
		 = append(, )
	}
	.right = .right
	return 
}

func addSeqs( *DoubleArray,  [][]int,  int,  node) {
	ensureSize(, )

	 := .children()
	var  int
	for  = 1; ; ++ {
		 := func() bool {
			for ,  := range  {
				 := .value()
				 :=  + 
				ensureSize(, )
				if .Check[] != 0 {
					return false
				}
			}
			return true
		}()
		if  {
			break
		}
	}
	.Base[] = 
	for ,  := range  {
		 := .value()
		 :=  + 
		.Check[] =  + 1
	}
	 := len(.Encoding)
	for ,  := range  {
		 := .value()
		if  ==  {
			continue
		}
		 :=  + 
		(, , , *)
	}
}

func ensureSize( *DoubleArray,  int) {
	for  >= len(.Base) {
		.Base = append(.Base, make([]int, len(.Base)+1)...)
		.Check = append(.Check, make([]int, len(.Check)+1)...)
	}
}

type byLex [][]int

func ( byLex) () int      { return len() }
func ( byLex) (,  int) { [], [] = [], [] }
func ( byLex) (,  int) bool {
	 := []
	 := []
	var  int
	for  = 0;  < len() &&  < len(); ++ {
		if [] < [] {
			return true
		}
		if [] > [] {
			return false
		}
	}
	return  < len()
}

// HasCommonPrefix determines if any sequence in the DoubleArray is a prefix of the given sequence.
func ( *DoubleArray) ( []string) bool {
	if len(.Base) == 0 {
		return false
	}

	var  int
	for ,  := range  {
		,  := .Encoding[]
		if ! {
			break
		}
		 := .Base[] + 
		if len(.Check) <=  || .Check[] != +1 {
			break
		}
		 = 
	}
	 := .Base[] + len(.Encoding)
	if len(.Check) <=  || .Check[] != +1 {
		return false
	}
	return true
}