【codevs3160】 LCS 【后缀自动机】

题意

  给出两个字符串,求它们的最长公共子串。

分析

  后缀自动机的基础应用。

  比如两个字符串s1和s2,我们把s1建为SAM,然后根据s2跑,找出s2每个前缀的最长公共后缀。

  我们可以理解为,当向尾部增加一个字母的时候,就按照匹配路径来走,当在SAM中找不到这样的字符串的时候,就要减少头部的字母,就顺着parent树往祖先结点走。

  

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

 

posted @ 2018-10-31 11:27  蒟蒻LQL  阅读(164)  评论(0编辑  收藏  举报