#include <iostream>
#include <cstring>
using namespace std;
struct Edge
{
int l, r, len;
}edge[400000];
struct Node
{
Node *node[28];
Edge *edge[28];
bool info;
int activeLength;
Node *suffixLink;
Node *parent;
int num;
}node[400000], *st;
char strTemp[200008], pattern[200008];
class SuffixTree
{
public:
int nodeNum, edgeNum;
Node roots;
Node* activeNode;
Node* addNode;
int minDistance, lastBound;
int n;
char *str;
int maping[128];
SuffixTree()
{
nodeNum=edgeNum=minDistance=lastBound=0;
memset(roots.node, NULL, sizeof(roots.node));
roots.info=false;
roots.suffixLink=&roots;
roots.activeLength=0;
roots.num=-1;
roots.parent=NULL;
activeNode=&roots;
addNode=NULL;
for(int i=0; i<128; i++)
maping[i]=26;
for(int i='a'; i<='z'; i++)
maping[i]=i-'a';
maping['#']=27;
}
void create(char *s, int l)
{
str=s;
n=l;
Node *help;
for(int i=0; i<n; i++)
{
activeNode=activeNode->suffixLink;
int start=i + activeNode->activeLength;
int minDistanceTemp=lastBound - activeNode->activeLength - i;
if(minDistanceTemp<0)
minDistanceTemp=0;
int t=maping[str[start]];
while(activeNode->node[t] != NULL &&
minDistanceTemp >= activeNode->edge[t]->len)
{
start=start + activeNode->edge[t]->len;
minDistanceTemp=minDistanceTemp - activeNode->edge[t]->len;
activeNode=activeNode->node[t];
t=maping[str[start]];
}
//沿边一个一个字符进行比较
help=activeNode;
bool flag=false;
int minDis=minDistanceTemp;
while(activeNode->node[t]!=NULL)
{
int record=maping[str[start]];
start += minDis;
int l=help->edge[record]->l;
int r=help->edge[record]->r;
for(int j=l+minDis; j<=r; j++, start++)
{
minDis=0;
if(str[j]!=str[start])
{
memset(node[nodeNum].node, NULL, sizeof(node[nodeNum].node));
node[nodeNum].info=false;
node[nodeNum].activeLength = activeNode->activeLength + (j-l);
node[nodeNum].num = nodeNum;
flag=true;
help->edge[t]->r = j-1;
help->edge[t]->len=j - help->edge[t]->l;
int tt=maping[str[j]];
node[nodeNum].edge[tt]=&edge[edgeNum];
edge[edgeNum].l=j;
edge[edgeNum].r=r;
edge[edgeNum].len=r-j+1;
node[nodeNum].node[tt]=help->node[t];
help->node[t]->parent=&node[nodeNum];
help->node[t]=&node[nodeNum];
node[nodeNum].parent = help;
help=&node[nodeNum];
++edgeNum;
++nodeNum;
goto ans;
}
}
activeNode=activeNode->node[t];
help=activeNode;
t=maping[str[start]];
}
ans:;
//增加新的信息节点
lastBound=start;
Node *stmp=help;
if(addNode!=NULL)
{
while(stmp->activeLength != addNode->activeLength-1)
stmp=stmp->parent;
addNode->suffixLink=stmp;
}
if(flag)
addNode=help;
else
addNode=NULL;
if(addNode!=NULL && addNode->activeLength == 1)
{
addNode->suffixLink=&roots;
addNode=NULL;
}
t=maping[str[start]];
memset(node[nodeNum].node, NULL, sizeof(node[nodeNum].node));
help->node[t]=&node[nodeNum];
help->edge[t]=&edge[edgeNum];
edge[edgeNum].l=start;
edge[edgeNum].r=n-1;
edge[edgeNum].len=n-start;
node[nodeNum].info=true;
node[nodeNum].num=nodeNum;
++nodeNum;
++edgeNum;
}
}
bool search(char *pattern)
{
int length=strlen(pattern), patLen=0;
Node *root=&roots;
while(true)
{
int temp=maping[pattern[patLen++]];
if(root->node[temp]==NULL)
return false;
if(patLen==length)
return true;
int l=root->edge[temp]->l+1, r=root->edge[temp]->r;
for(int i=l; i<=r; i++)
{
if(str[i]!=pattern[patLen++])
return false;
if(patLen==length)
return true;
}
root=root->node[temp];
}
}
void dfs(Node *st, int l)
{
if(st->info)
{
printf("/n");
return;
}
printf("它的儿子节点如下:/n");
l=l+4;
for(int i=0; i<28; i++)
{
if(st->node[i])
{
for(int j=0; j<l; j++)
printf(" ");
printf("%d ", st->edge[i]->l+1);
for(int j=st->edge[i]->l; j<=st->edge[i]->r; j++)
printf("%c", strTemp[j]);
dfs(st->node[i], l+st->edge[i]->len);
}
}
}
~SuffixTree()
{
nodeNum=edgeNum=minDistance=lastBound=0;
memset(roots.node, NULL, sizeof(roots.node));
roots.info=false;
roots.suffixLink=&roots;
roots.activeLength=0;
}
}suffixTree;
int main()
{
printf("请输入字符串(只支持小写字母):");
scanf("%s", &strTemp);
int l=strlen(strTemp);
strTemp[l++]='#';
strTemp[l]='/0';
suffixTree.create(strTemp, l);
st=&suffixTree.roots;
suffixTree.dfs(st, 0);
printf("请输入模式串(输入EOF结束):");
while(scanf("%s", &pattern)!=EOF)
{
bool ret=suffixTree.search(pattern);
if(ret)
printf("%s 是其子串/n", pattern);
else
printf("%s 不是其子串/n", pattern);
printf("请输入模式串(输入EOF结束):");
}
return 0;
}
#include <cstring>
using namespace std;
struct Edge
{
int l, r, len;
}edge[400000];
struct Node
{
Node *node[28];
Edge *edge[28];
bool info;
int activeLength;
Node *suffixLink;
Node *parent;
int num;
}node[400000], *st;
char strTemp[200008], pattern[200008];
class SuffixTree
{
public:
int nodeNum, edgeNum;
Node roots;
Node* activeNode;
Node* addNode;
int minDistance, lastBound;
int n;
char *str;
int maping[128];
SuffixTree()
{
nodeNum=edgeNum=minDistance=lastBound=0;
memset(roots.node, NULL, sizeof(roots.node));
roots.info=false;
roots.suffixLink=&roots;
roots.activeLength=0;
roots.num=-1;
roots.parent=NULL;
activeNode=&roots;
addNode=NULL;
for(int i=0; i<128; i++)
maping[i]=26;
for(int i='a'; i<='z'; i++)
maping[i]=i-'a';
maping['#']=27;
}
void create(char *s, int l)
{
str=s;
n=l;
Node *help;
for(int i=0; i<n; i++)
{
activeNode=activeNode->suffixLink;
int start=i + activeNode->activeLength;
int minDistanceTemp=lastBound - activeNode->activeLength - i;
if(minDistanceTemp<0)
minDistanceTemp=0;
int t=maping[str[start]];
while(activeNode->node[t] != NULL &&
minDistanceTemp >= activeNode->edge[t]->len)
{
start=start + activeNode->edge[t]->len;
minDistanceTemp=minDistanceTemp - activeNode->edge[t]->len;
activeNode=activeNode->node[t];
t=maping[str[start]];
}
//沿边一个一个字符进行比较
help=activeNode;
bool flag=false;
int minDis=minDistanceTemp;
while(activeNode->node[t]!=NULL)
{
int record=maping[str[start]];
start += minDis;
int l=help->edge[record]->l;
int r=help->edge[record]->r;
for(int j=l+minDis; j<=r; j++, start++)
{
minDis=0;
if(str[j]!=str[start])
{
memset(node[nodeNum].node, NULL, sizeof(node[nodeNum].node));
node[nodeNum].info=false;
node[nodeNum].activeLength = activeNode->activeLength + (j-l);
node[nodeNum].num = nodeNum;
flag=true;
help->edge[t]->r = j-1;
help->edge[t]->len=j - help->edge[t]->l;
int tt=maping[str[j]];
node[nodeNum].edge[tt]=&edge[edgeNum];
edge[edgeNum].l=j;
edge[edgeNum].r=r;
edge[edgeNum].len=r-j+1;
node[nodeNum].node[tt]=help->node[t];
help->node[t]->parent=&node[nodeNum];
help->node[t]=&node[nodeNum];
node[nodeNum].parent = help;
help=&node[nodeNum];
++edgeNum;
++nodeNum;
goto ans;
}
}
activeNode=activeNode->node[t];
help=activeNode;
t=maping[str[start]];
}
ans:;
//增加新的信息节点
lastBound=start;
Node *stmp=help;
if(addNode!=NULL)
{
while(stmp->activeLength != addNode->activeLength-1)
stmp=stmp->parent;
addNode->suffixLink=stmp;
}
if(flag)
addNode=help;
else
addNode=NULL;
if(addNode!=NULL && addNode->activeLength == 1)
{
addNode->suffixLink=&roots;
addNode=NULL;
}
t=maping[str[start]];
memset(node[nodeNum].node, NULL, sizeof(node[nodeNum].node));
help->node[t]=&node[nodeNum];
help->edge[t]=&edge[edgeNum];
edge[edgeNum].l=start;
edge[edgeNum].r=n-1;
edge[edgeNum].len=n-start;
node[nodeNum].info=true;
node[nodeNum].num=nodeNum;
++nodeNum;
++edgeNum;
}
}
bool search(char *pattern)
{
int length=strlen(pattern), patLen=0;
Node *root=&roots;
while(true)
{
int temp=maping[pattern[patLen++]];
if(root->node[temp]==NULL)
return false;
if(patLen==length)
return true;
int l=root->edge[temp]->l+1, r=root->edge[temp]->r;
for(int i=l; i<=r; i++)
{
if(str[i]!=pattern[patLen++])
return false;
if(patLen==length)
return true;
}
root=root->node[temp];
}
}
void dfs(Node *st, int l)
{
if(st->info)
{
printf("/n");
return;
}
printf("它的儿子节点如下:/n");
l=l+4;
for(int i=0; i<28; i++)
{
if(st->node[i])
{
for(int j=0; j<l; j++)
printf(" ");
printf("%d ", st->edge[i]->l+1);
for(int j=st->edge[i]->l; j<=st->edge[i]->r; j++)
printf("%c", strTemp[j]);
dfs(st->node[i], l+st->edge[i]->len);
}
}
}
~SuffixTree()
{
nodeNum=edgeNum=minDistance=lastBound=0;
memset(roots.node, NULL, sizeof(roots.node));
roots.info=false;
roots.suffixLink=&roots;
roots.activeLength=0;
}
}suffixTree;
int main()
{
printf("请输入字符串(只支持小写字母):");
scanf("%s", &strTemp);
int l=strlen(strTemp);
strTemp[l++]='#';
strTemp[l]='/0';
suffixTree.create(strTemp, l);
st=&suffixTree.roots;
suffixTree.dfs(st, 0);
printf("请输入模式串(输入EOF结束):");
while(scanf("%s", &pattern)!=EOF)
{
bool ret=suffixTree.search(pattern);
if(ret)
printf("%s 是其子串/n", pattern);
else
printf("%s 不是其子串/n", pattern);
printf("请输入模式串(输入EOF结束):");
}
return 0;
}