SPOJ1811最长公共子串问题(后缀自动机)

转载:http://blog.csdn.net/acdreamers/article/details/10746023

 

题意:给两个串A和B,求这两个串的最长公共子串。

分析:其实本题用后缀数组的DC3已经能很好的解决,这里我们来说说利用后缀自动机如何实现。

对于串A和B,我们先构造出串A的后缀自动机,那么然后用B串去匹配,对于B,我们一位一位地扫描,维护一个ans值,表示从

B串的开始到B[i]的这个子串与A的最长公共子串。

假设现在到B[i-1]的最长公共子串长度为ans,然后我们来看B[i],如果当前节点有B[i]这个孩子,那么直接就len++即可。

如果没有就找一直向前找pre,直到找到有B[i]这个孩子的节点。

 

 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stdio.h>
 5 
 6 using namespace std;
 7 const int N=250005;
 8 
 9 struct State
10 {
11     State *pre,*go[26];
12     int step;
13     void clear()
14     {
15         pre=0;
16         step=0;
17         memset(go,0,sizeof(go));
18     }
19 }*root,*last;
20 
21 State statePool[N*2],*cur;
22 
23 void init()
24 {
25     cur=statePool;
26     root=last=cur++;
27     root->clear();
28 }
29 
30 void Insert(int w)
31 {
32     State *p=last;
33     State *np=cur++;
34     np->clear();
35     np->step=p->step+1;
36     while(p&&!p->go[w])
37         p->go[w]=np,p=p->pre;
38     if(p==0)
39         np->pre=root;
40     else
41     {
42         State *q=p->go[w];
43         if(p->step+1==q->step)
44             np->pre=q;
45         else
46         {
47             State *nq=cur++;
48             nq->clear();
49             memcpy(nq->go,q->go,sizeof(q->go));
50             nq->step=p->step+1;
51             nq->pre=q->pre;
52             q->pre=nq;
53             np->pre=nq;
54             while(p&&p->go[w]==q)
55                 p->go[w]=nq, p=p->pre;
56         }
57     }
58     last=np;
59 }
60 
61 char A[N],B[N];
62 
63 int main()
64 {
65     int n,m;
66     scanf("%s%s",A,B);
67     n=strlen(A);
68     m=strlen(B);
69     init();
70     for(int i=0; i<n; i++)
71         Insert(A[i]-'a');
72     int ans=0,len=0;
73     State *p=root;
74     for(int i=0; i<m; i++)
75     {
76         int x=B[i]-'a';
77         if(p->go[x])
78         {
79             len++;
80             p=p->go[x];
81         }
82         else
83         {
84             while(p&&!p->go[x]) p=p->pre;
85             if(!p) p=root,len=0;
86             else   len=p->step+1,p=p->go[x];
87         }
88         ans=max(ans,len);
89     }
90     printf("%d\n",ans);
91     return 0;
92 }

 

posted @ 2017-10-19 23:06  抓不住Jerry的Tom  阅读(268)  评论(0编辑  收藏  举报