Task: Eertree




Go: package main

import "fmt"

func main() {
    tree := eertree([]byte("eertree"))
    fmt.Println(subPalindromes(tree))
}

type edges map[byte]int

type node struct {
    length int
    edges
    suffix int
}

const evenRoot = 0
const oddRoot = 1

func eertree(s []byte) []node {
    tree := []node{
        evenRoot: {length: 0, suffix: oddRoot, edges: edges{}},
        oddRoot:  {length: -1, suffix: oddRoot, edges: edges{}},
    }
    suffix := oddRoot
    var n, k int
    for i, c := range s {
        for n = suffix; ; n = tree[n].suffix {
            k = tree[n].length
            if b := i - k - 1; b >= 0 && s[b] == c {
                break
            }
        }
        if e, ok := tree[n].edges[c]; ok {
            suffix = e
            continue
        }
        suffix = len(tree)
        tree = append(tree, node{length: k + 2, edges: edges{}})
        tree[n].edges[c] = suffix
        if tree[suffix].length == 1 {
            tree[suffix].suffix = 0
            continue
        }
        for {
            n = tree[n].suffix
            if b := i - tree[n].length - 1; b >= 0 && s[b] == c {
                break
            }
        }
        tree[suffix].suffix = tree[n].edges[c]
    }
    return tree
}

func subPalindromes(tree []node) (s []string) {
    var children func(int, string)
    children = func(n int, p string) {
        for c, n := range tree[n].edges {
            c := string(c)
            p := c + p + c
            s = append(s, p)
            children(n, p)
        }
    }
    children(0, "")
    for c, n := range tree[1].edges {
        c := string(c)
        s = append(s, c)
        children(n, c)
    }
    return
}




Python: 
from __future__ import print_function

class Node(object):
	def __init__(self):
		self.edges = {} 
		self.link = None 
		self.len = 0 

class Eertree(object):
	def __init__(self):
		self.nodes = []
		
		self.rto = Node() 
		self.rte = Node() 

		
		self.rto.link = self.rte.link = self.rto;
		self.rto.len = -1
		self.rte.len = 0
		self.S = [0] 
		self.maxSufT = self.rte 

	def get_max_suffix_pal(self, startNode, a):
		
		
		
		u = startNode
		i = len(self.S)
		k = u.len
		while id(u) != id(self.rto) and self.S[i - k - 1] != a:
			assert id(u) != id(u.link) 
			u = u.link
			k = u.len

		return u
	
	def add(self, a):

		
		
		
		
		Q = self.get_max_suffix_pal(self.maxSufT, a)

		
		createANewNode = not a in Q.edges

		if createANewNode:
			
			P = Node()
			self.nodes.append(P)
			P.len = Q.len + 2
			if P.len == 1:
				
				P.link = self.rte
			else:
				
				
				
				P.link = self.get_max_suffix_pal(Q.link, a).edges[a]

			
			Q.edges[a] = P

		
		self.maxSufT = Q.edges[a]

		
		self.S.append(a)

		return createANewNode
	
	def get_sub_palindromes(self, nd, nodesToHere, charsToHere, result):
		
		

		
		for lnkName in nd.edges:
			nd2 = nd.edges[lnkName] 
			self.get_sub_palindromes(nd2, nodesToHere+[nd2], charsToHere+[lnkName], result)

		
		if id(nd) != id(self.rto) and id(nd) != id(self.rte): 
			tmp = "".join(charsToHere)
			if id(nodesToHere[0]) == id(self.rte): 
				assembled = tmp[::-1] + tmp
			else: 
				assembled = tmp[::-1] + tmp[1:]
			result.append(assembled)

if __name__=="__main__":
	st = "eertree"
	print ("Processing string", st)
	eertree = Eertree()
	for ch in st:
		eertree.add(ch)

	print ("Number of sub-palindromes:", len(eertree.nodes))

	
	result = []
	eertree.get_sub_palindromes(eertree.rto, [eertree.rto], [], result) 
	eertree.get_sub_palindromes(eertree.rte, [eertree.rte], [], result) 
	print ("Sub-palindromes:", result)