我是不是真的需要学学后缀数组了,这个题我是用后缀自动机写出来的。写的比较辛苦吧,不过对后缀自动机的理解又进了一步。不废话了,题意是让你求两个字符串的最长公共子串的长度。
现在贴上我的代码:
View Code
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <queue> #include <map> using namespace std; const int maxlen=100000+5; char s1[maxlen],s2[maxlen]; int cnt; struct node { int len; node *next[26]; node *fail; }memory[1000000]; node *createnode(int l,node *fail) { node *p=&memory[cnt]; memory[cnt].len=l; memory[cnt].fail=fail; memset(memory[cnt++].next,NULL,sizeof(node *)*26); return p; } class SAM { public: node *root; SAM() { root=NULL; } void Insert(char *str) { if(!root) root=createnode(0,NULL); node *loca=root; for(int i=0;str[i];i++) { int num=str[i]-'a'; if(loca->next[num]==NULL) loca->next[num]=createnode(i+1,NULL); loca=loca->next[num]; } } void Build() { std::queue<node *>s; while(!s.empty()) s.pop(); s.push(root); while(!s.empty()) { node *loca=s.front(); s.pop(); for(int i=0;i<26;i++) { if(loca->next[i]!=NULL) { if(loca==root) loca->next[i]->fail=root; else { node *tmp=loca->fail; while(tmp!=NULL) { if(tmp->next[i]!=NULL) break; tmp->next[i]=loca->next[i]; tmp=tmp->fail; } if(tmp==NULL) loca->next[i]->fail=root; else if(tmp->next[i]->len==tmp->len+1) loca->next[i]->fail=tmp->next[i]; else { node *t=tmp->next[i]; node *nt=createnode(tmp->len+1,t->fail); t->fail=loca->next[i]->fail=nt; memcpy(nt->next,t->next,sizeof(node *)*26); while(tmp&&tmp->next[i]==t) { tmp->next[i]=nt; tmp=tmp->fail; } } } s.push(loca->next[i]); } } } } int maxCommonLen(char *s1,char *s2) { node *loca=root; int ans,len; ans=len=0; for(int i=0;s2[i];i++) { int num=s2[i]-'a'; if(loca->next[num]) { len++; loca=loca->next[num]; } else { node *tmp=loca->fail; while(tmp&&!tmp->next[num]) tmp=tmp->fail; if(tmp) { len=tmp->len+1; loca=tmp->next[num]; } else { loca=root; len=0; } } ans=(ans<len)?len:ans; } return ans; } }; int main() { while(~scanf("%s %s",s1,s2)) { SAM sam; cnt=0; sam.Insert(s1); sam.Build(); printf("%d\n",sam.maxCommonLen(s1,s2)); } return 0; }
之前自己曾在百度知道上面问了个问题,内容是,字符串的处理,我该怎么来学,前提我当时学会了kmp和字典树,回答是让我把ac自动机跟后缀数组再学一下。我真的需要学习一下后缀数组嘛?说实话我对后缀数组思路里面的那几个数组实在是不怎么感冒。所以就直接绕来学后缀自动机了。请大牛为我指条明路!