#include<bits/stdc++.h>
#define MAX_CHAR 256
using
namespace
std;
struct
SuffixTreeNode {
struct
SuffixTreeNode *children[MAX_CHAR];
struct
SuffixTreeNode *suffixLink;
int
start;
int
*end;
int
suffixIndex;
unordered_set<
int
> *forwardIndices;
unordered_set<
int
> *reverseIndices;
};
typedef
struct
SuffixTreeNode Node;
char
text[100];
Node *root = NULL;
Node *lastNewNode = NULL;
Node *activeNode = NULL;
int
activeEdge = -1;
int
activeLength = 0;
int
remainingSuffixCount = 0;
int
leafEnd = -1;
int
*rootEnd = NULL;
int
*splitEnd = NULL;
int
size = -1;
int
size1 = 0;
int
reverseIndex;
unordered_set<
int
>::iterator forwardIndex;
Node *newNode(
int
start,
int
*end)
{
Node *node =(Node*)
malloc
(
sizeof
(Node));
int
i;
for
(i = 0; i < MAX_CHAR; i++)
node->children[i] = NULL;
node->suffixLink = root;
node->start = start;
node->end = end;
node->suffixIndex = -1;
node->forwardIndices =
new
unordered_set<
int
>;
node->reverseIndices =
new
unordered_set<
int
>;
return
node;
}
int
edgeLength(Node *n) {
if
(n == root)
return
0;
return
*(n->end) - (n->start) + 1;
}
int
walkDown(Node *currNode)
{
if
(activeLength >= edgeLength(currNode))
{
activeEdge += edgeLength(currNode);
activeLength -= edgeLength(currNode);
activeNode = currNode;
return
1;
}
return
0;
}
void
extendSuffixTree(
int
pos)
{
leafEnd = pos;
remainingSuffixCount++;
lastNewNode = NULL;
while
(remainingSuffixCount > 0) {
if
(activeLength == 0)
activeEdge = pos;
if
(activeNode->children] == NULL)
{
activeNode->children] =
newNode(pos, &leafEnd);
if
(lastNewNode != NULL)
{
lastNewNode->suffixLink = activeNode;
lastNewNode = NULL;
}
}
else
{
Node *next = activeNode->children] ;
if
(walkDown(next))
{
continue
;
}
if
(text[next->start + activeLength] == text[pos])
{
activeLength++;
break
;
}
splitEnd = (
int
*)
malloc
(
sizeof
(
int
));
*splitEnd = next->start + activeLength - 1;
Node *split = newNode(next->start, splitEnd);
activeNode->children] = split;
split->children] = newNode(pos, &leafEnd);
next->start += activeLength;
split->children] = next;
if
(lastNewNode != NULL)
{
lastNewNode->suffixLink = split;
}
lastNewNode = split;
}
remainingSuffixCount--;
if
(activeNode == root && activeLength > 0)
{
activeLength--;
activeEdge = pos - remainingSuffixCount + 1;
}
else
if
(activeNode != root)
{
activeNode = activeNode->suffixLink;
}
}
}
void
print(
int
i,
int
j)
{
int
k;
for
(k=i; k<=j && text[k] !=
'#'
; k++)
printf
(
"%c"
, text[k]);
if
(k<=j)
printf
(
"#"
);
}
void
setSuffixIndexByDFS(Node *n,
int
labelHeight)
{
if
(n == NULL)
return
;
if
(n->start != -1)
{
}
int
leaf = 1;
int
i;
for
(i = 0; i < MAX_CHAR; i++)
{
if
(n->children[i] != NULL)
{
leaf = 0;
setSuffixIndexByDFS(n->children[i], labelHeight +
edgeLength(n->children[i]));
if
(n != root)
{
n->forwardIndices->insert(
n->children[i]->forwardIndices->begin(),
n->children[i]->forwardIndices->end());
n->reverseIndices->insert(
n->children[i]->reverseIndices->begin(),
n->children[i]->reverseIndices->end());
}
}
}
if
(leaf == 1)
{
for
(i= n->start; i<= *(n->end); i++)
{
if
(text[i] ==
'#'
)
{
n->end = (
int
*)
malloc
(
sizeof
(
int
));
*(n->end) = i;
}
}
n->suffixIndex = size - labelHeight;
if
(n->suffixIndex < size1)
n->forwardIndices->insert(n->suffixIndex);
else
n->reverseIndices->insert(n->suffixIndex - size1);
}
}
void
freeSuffixTreeByPostOrder(Node *n)
{
if
(n == NULL)
return
;
int
i;
for
(i = 0; i < MAX_CHAR; i++)
{
if
(n->children[i] != NULL)
{
freeSuffixTreeByPostOrder(n->children[i]);
}
}
if
(n->suffixIndex == -1)
free
(n->end);
free
(n);
}
void
buildSuffixTree()
{
size =
strlen
(text);
int
i;
rootEnd = (
int
*)
malloc
(
sizeof
(
int
));
*rootEnd = - 1;
root = newNode(-1, rootEnd);
activeNode = root;
for
(i=0; i<size; i++)
extendSuffixTree(i);
int
labelHeight = 0;
setSuffixIndexByDFS(root, labelHeight);
}
void
doTraversal(Node *n,
int
labelHeight,
int
* maxHeight,
int
* substringStartIndex)
{
if
(n == NULL)
{
return
;
}
int
i=0;
int
ret = -1;
if
(n->suffixIndex < 0)
{
for
(i = 0; i < MAX_CHAR; i++)
{
if
(n->children[i] != NULL)
{
doTraversal(n->children[i], labelHeight +
edgeLength(n->children[i]),
maxHeight, substringStartIndex);
if
(*maxHeight < labelHeight
&& n->forwardIndices->size() > 0 &&
n->reverseIndices->size() > 0)
{
for
(forwardIndex=n->forwardIndices->begin();
forwardIndex!=n->forwardIndices->end();
++forwardIndex)
{
reverseIndex = (size1 - 2) -
(*forwardIndex + labelHeight - 1);
if
(n->reverseIndices->find(reverseIndex) !=
n->reverseIndices->end())
{
*maxHeight = labelHeight;
*substringStartIndex = *(n->end) -
labelHeight + 1;
break
;
}
}
}
}
}
}
}
void
getLongestPalindromicSubstring()
{
int
maxHeight = 0;
int
substringStartIndex = 0;
doTraversal(root, 0, &maxHeight, &substringStartIndex);
int
k;
for
(k=0; k<maxHeight; k++)
printf
(
"%c"
, text[k + substringStartIndex]);
if
(k == 0)
printf
(
"No palindromic substring"
);
else
printf
(
", of length: %d"
,maxHeight);
printf
(
"\n"
);
}
int
main(
int
argc,
char
*argv[])
{
size1 = 9;
printf
(
"Longest Palindromic Substring in cabbaabb is: "
);
strcpy
(text,
"cabbaabb#bbaabbac$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 17;
printf
(
"Longest Palindromic Substring in forgeeksskeegfor is: "
);
strcpy
(text,
"forgeeksskeegfor#rofgeeksskeegrof$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 6;
printf
(
"Longest Palindromic Substring in abcde is: "
);
strcpy
(text,
"abcde#edcba$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 7;
printf
(
"Longest Palindromic Substring in abcdae is: "
);
strcpy
(text,
"abcdae#eadcba$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 6;
printf
(
"Longest Palindromic Substring in abacd is: "
);
strcpy
(text,
"abacd#dcaba$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 6;
printf
(
"Longest Palindromic Substring in abcdc is: "
);
strcpy
(text,
"abcdc#cdcba$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 13;
printf
(
"Longest Palindromic Substring in abacdfgdcaba is: "
);
strcpy
(text,
"abacdfgdcaba#abacdgfdcaba$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 15;
printf
(
"Longest Palindromic Substring in xyabacdfgdcaba is: "
);
strcpy
(text,
"xyabacdfgdcaba#abacdgfdcabayx$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 9;
printf
(
"Longest Palindromic Substring in xababayz is: "
);
strcpy
(text,
"xababayz#zyababax$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
size1 = 6;
printf
(
"Longest Palindromic Substring in xabax is: "
);
strcpy
(text,
"xabax#xabax$"
); buildSuffixTree();
getLongestPalindromicSubstring();
freeSuffixTreeByPostOrder(root);
return
0;
}