【SPOJ - LCS2】Longest Common Substring II【SAM】

题意

  求出多个串的最长公共子串。

分析

   刚学SAM想做这个题的话最好先去做一下那道codevs3160。求两个串的LCS应该怎么求?把一个串s1建自动机,然后跑另一个串s2,然后找出s2每个前缀的最长公共后缀。那么多个的时候,我们也用这种类似的方法,但是我们求最长公共后缀的时候要求第一个串的。我们把其中一个串建SAM,然后把其他的串都在上面跑,维护两个值,Max[u]和Min[u]。自动机中每个状态u的Right存的是结尾集合。那么对于一个字符串,我们可以求出他和自动机中每个状态的最长公共后缀。然后,我们通过Max[fa[u]]=max(Max[fa[u]],Max[u])来确定左右状态的最长公共后缀,然后更新Min[o]。

下面的代码没有AC,但是我找了好久BUG没找到··如果有人看完并且找到了bug麻烦跟我说一下万分感谢!

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 const int maxn=300000+100;
 8 char s[maxn];
 9 struct state{
10     int len,link;
11     int next[26];
12 }st[2*maxn];
13 int n,last,cur,sz;
14 int Min[2*maxn],Max[2*maxn],c[2*maxn];
15 
16 void init(){
17     sz=1;
18     cur=last=0;
19     st[0].link=-1;
20     st[0].len=0;
21 }
22 
23 void build_sam(int c){
24     cur=sz++;
25     st[cur].len=st[last].len+1;
26     Min[cur]=st[cur].len;
27     int p;
28     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link)
29         st[p].next[c]=cur;
30     if(p==-1)
31         st[cur].link=0;
32     else{
33         int q=st[p].next[c];
34         if(st[q].len==st[p].len+1)
35             st[cur].link=q;
36         else{
37             int clone=sz++;
38             st[clone].len=st[p].len+1;
39             Min[clone]=st[clone].len;
40             st[clone].link=st[q].link;
41             for(int i=0;i<26;i++)
42                 st[clone].next[i]=st[q].next[i];
43             for(;p!=-1&&st[p].next[c]==q;p=st[p].link)
44                 st[p].next[c]=clone;
45             st[cur].link=st[q].link=clone;
46         }
47     }
48     last=cur;
49 }
50 
51 int cmp(int a,int b){
52     return st[a].len<st[b].len;
53 }
54 
55 int main(){
56     scanf("%s",s);
57     n=strlen(s);
58     init();
59 
60     for(int i=0;i<n;i++)
61         build_sam(s[i]-'a');
62     for(int i=0;i<sz;i++)
63         c[i]=i;
64     sort(c,c+sz,cmp);
65 
66     while(scanf("%s",s)!=EOF){
67         n=strlen(s);
68         int u=0,len=0;
69         for(int i=0;i<n;i++){
70             int c=s[i]-'a';
71             if(u!=-1&&st[u].next[c]==0)
72                 u=st[u].link,len=st[u].len;
73             if(u==-1)
74                 u=0,len=0;
75             else{
76                 u=st[u].next[c];
77                 len++;
78                 Max[u]=max(Max[u],len);
79             }
80         }
81 
82         for(int i=sz-1;i>=0;i--){
83             int o=c[i];
84             Min[o]=min(Min[o],Max[o]);
85             if(st[o].link!=-1){
86                 Max[st[o].link]=max(Max[st[o].link],Max[o]);
87             }
88             Max[o]=0;
89         }
90     }
91     int ans=0;
92     for(int i=0;i<sz;i++){
93         ans=max(ans,Min[i]);
94     }
95     printf("%d\n",ans);
96 
97 return 0;
98 }
View Code

猜你喜欢

转载自www.cnblogs.com/LQLlulu/p/9885912.html