public static string FindLargestPalindrome(string s) { if (s.Length == 0) { return(string.Empty); } if (s.Length == 1) { return(s[0].ToString()); } var rs = new string(s.Reverse().ToArray()); var ns = s + '\0' + rs; var suffixTree = SuffixTreeNode.Build(ns); var Earray = new int[(ns.Length + 2) * 4 - 1]; var Aarray = new int[(ns.Length + 2) * 4 - 1]; var Rarray = new int[ns.Length + 1]; suffixTree.WriteToArrays(Earray, 0, Aarray, Rarray); var rmqHelper = new RMQPM1Helper(Aarray); var lenMaxPalindrome = 0; var midPalindrome = -1; for (int i = 0; i < s.Length; i++) { var indL = Rarray[i + 1]; var indR = Rarray[ns.Length - i]; if (indL > indR) { int tmp = indL; indL = indR; indR = tmp; } int indexInE = rmqHelper.GetMinimum(indL, indR).Index; var palindromeLength = Earray[indexInE]; if (palindromeLength > lenMaxPalindrome) { lenMaxPalindrome = palindromeLength; midPalindrome = i + 1; } } var startPalindrome = midPalindrome - lenMaxPalindrome; var endPalindrome = startPalindrome + 2 * lenMaxPalindrome - 2; var lenPalindrome = endPalindrome - startPalindrome + 1; var r = s.Substring(startPalindrome, lenPalindrome); return(r); }
public static SuffixTreeNode Build(string s) { var s2 = '\t' + s + '\t'; var root = new SuffixTreeNode(0, 0, 0); for (int i = 1; i < s2.Length - 1; i++) { var currentNode = root; var indexInWord = i; bool alreadyAdded = false; while (currentNode.children.TryGetValue(s2[indexInWord], out SuffixTreeNode searchedChild)) { int endMatchIndex = indexInWord; int indInFound = searchedChild.startIndex; while (s2[endMatchIndex] == s2[indInFound] && indInFound <= searchedChild.endIndex) { endMatchIndex++; indInFound++; } bool wholeWord = indInFound == searchedChild.endIndex + 1; if (!wholeWord) { var nodeOldChildren = new SuffixTreeNode(indInFound, searchedChild.endIndex, searchedChild.subwordStartIndex); nodeOldChildren.children = searchedChild.children; var newNode = new SuffixTreeNode(endMatchIndex, s2.Length - 1, i); searchedChild.children = new Dictionary <char, SuffixTreeNode> { { s2[indInFound], nodeOldChildren }, { s2[endMatchIndex], newNode } }; searchedChild.endIndex = indInFound - 1; alreadyAdded = true; break; } else { currentNode = searchedChild; indexInWord = endMatchIndex; } } if (!alreadyAdded) { var newNode = new SuffixTreeNode(indexInWord, s2.Length - 1, i); currentNode.children.Add(s2[indexInWord], newNode); } } root.UpdateDepth(0); return(root); }