Task: Eertree



C#: using System;
using System.Collections.Generic;

namespace Eertree {
    class Node {
        public Node(int length) {
            this.Length = length;
            
            this.Edges = new Dictionary<char, int>();
        }

        public Node(int length, Dictionary<char, int> edges, int suffix) {
            this.Length = length;
            this.Edges = edges;
            this.Suffix = suffix;
        }

        public int Length { get; set; }
        public Dictionary<char, int> Edges { get; set; }
        public int Suffix { get; set; }
    }

    class Program {
        const int EVEN_ROOT = 0;
        const int ODD_ROOT = 1;

        static List<Node> Eertree(string s) {
            List<Node> tree = new List<Node> {
                
                new Node(0, new Dictionary<char, int>(), ODD_ROOT),
                
                new Node(-1, new Dictionary<char, int>(), ODD_ROOT)
            };
            int suffix = ODD_ROOT;
            int n, k;
            for (int i = 0; i < s.Length; i++) {
                char c = s[i];
                for (n = suffix; ; n = tree[n].Suffix) {
                    k = tree[n].Length;
                    int b = i - k - 1;
                    if (b >= 0 && s[b] == c) {
                        break;
                    }
                }
                if (tree[n].Edges.ContainsKey(c)) {
                    suffix = tree[n].Edges[c];
                    continue;
                }
                suffix = tree.Count;
                tree.Add(new Node(k + 2));
                tree[n].Edges[c] = suffix;
                if (tree[suffix].Length == 1) {
                    tree[suffix].Suffix = 0;
                    continue;
                }
                while (true) {
                    n = tree[n].Suffix;
                    int b = i - tree[n].Length - 1;
                    if (b >= 0 && s[b] == c) {
                        break;
                    }
                }
                tree[suffix].Suffix = tree[n].Edges[c];
            }
            return tree;
        }

        static List<string> SubPalindromes(List<Node> tree) {
            List<string> s = new List<string>();
            SubPalindromes_children(0, "", tree, s);
            foreach (var c in tree[1].Edges.Keys) {
                int m = tree[1].Edges[c];
                string ct = c.ToString();
                s.Add(ct);
                SubPalindromes_children(m, ct, tree, s);
            }
            return s;
        }

        static void SubPalindromes_children(int n, string p, List<Node> tree, List<string> s) {
            foreach (var c in tree[n].Edges.Keys) {
                int m = tree[n].Edges[c];
                string p1 = c + p + c;
                s.Add(p1);
                SubPalindromes_children(m, p1, tree, s);
            }
        }

        static void Main(string[] args) {
            List<Node> tree = Eertree("eertree");
            List<string> result = SubPalindromes(tree);
            string listStr = string.Join(", ", result);
            Console.WriteLine("[{0}]", listStr);
        }
    }
}





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)