SPOJ-LCS Longest Common Substring 【后缀自动机】

题目分析:

用没出现过的字符搞拼接。搞出right树,找right集合的最小和最大。如果最小和最大分居两侧可以更新答案。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1000500;
 5 
 6 int son[maxn][30],fa[maxn],maxlen[maxn],root,num,sigma = 27;
 7 int minn[maxn],maxx[maxn];// lright rright
 8 
 9 string str,ss;
10 int n,m;
11 vector<int> T[maxn];
12 
13 int addnew(int dt){maxlen[++num] = dt;return num;}
14 int ins(char x,int p,int hhhh){
15     int np = addnew(maxlen[p]+1); minn[np] = maxx[np] = hhhh;
16     while(p && !son[p][x-'a']) son[p][x-'a'] = np,p = fa[p];
17     if(!p){fa[np] = root; return np;}
18     else{
19     int q = son[p][x-'a'];
20     if(maxlen[q]==maxlen[p]+1){fa[np]=q;return np;}
21     else{
22         int nq = addnew(maxlen[p]+1);
23         for(int i=0;i<sigma;i++) son[nq][i] = son[q][i];
24         fa[nq] = fa[q]; fa[q] = fa[np] = nq;
25         while(p && son[p][x-'a'] == q) son[p][x-'a'] = nq,p = fa[p];
26         return np;
27     }
28     }
29 }
30 
31 void dfs(int now){
32     if(!minn[now]) minn[now] = 1e9;
33     for(int i=0;i<T[now].size();i++){
34     dfs(T[now][i]);
35     minn[now] = min(minn[now],minn[T[now][i]]);
36     maxx[now] = max(maxx[now],maxx[T[now][i]]);
37     }
38 }
39 
40 void work(){
41     int lst = addnew(0);root = lst;
42     for(int i=0;i<str.length();i++)
43     lst = ins(str[i],lst,i+1);
44     for(int i=2;i<=num;i++) T[fa[i]].push_back(i);
45     dfs(1); int ans = 0;
46     for(int i=1;i<=num;i++)if(minn[i]<=n&&maxx[i]>n+1)ans=max(ans,maxlen[i]);
47     cout<<ans<<endl;
48 }
49 
50 int main(){
51     ios::sync_with_stdio(false);
52     cin.tie(0);
53     cin >> str; cin >> ss;
54     n = str.length(); m = ss.length();
55     str += ('z'+1); str += ss;
56     work();
57     return 0;
58 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/10306444.html