【后缀自动机】SPOJ 1812-LCSII
题意:
给出最多10个长度不超过100000的字符串,求他们的LCS的长度。时限是鬼畜的0.25s 。
后缀自动机练习...虽然有人这么说但我并不觉得hash能过。
本题可以说是【论SAM中按step排序更新pre的重要性】:
总的来说做法和1811-LCS有点类似,不同的是因为有多个字符串,因此每个字符串都需要在SAM上跑一次。
记录下每个节点最长能容纳长度为多少的字符,最后取个MAX就行了。
用nans[i]表示匹配当前字符串时,i号点能容纳的子串长度,如果i的pre上的当前答案比i还要小的话就用nans[i]来更新nans[i.pre] 。
用ans表示所有nans的最小值,在计算每个字符串时用nans来更新ans,最后在ans中找一个MAX就可以了。
一开始忘记了黑体的那句话,结果拍了很久又没拍出来,提交的时候在第10个点WA了简直难过...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #define maxn 105000*2 6 using namespace std; 7 8 struct node { int s[26],pre; } Suf[maxn]; 9 char S[maxn],T[maxn]; 10 int i,j,n,m,k,len1,len2,len,last = 1,root = 1,cnt = 1; 11 int step[maxn],nans[maxn],ans[maxn],f[maxn]; 12 13 void add(int nxt) 14 { 15 int now = ++cnt, p = last; 16 step[now] = step[p] + 1; 17 for ( ; p != 0 && Suf[p].s[nxt] == 0; p = Suf[p].pre) Suf[p].s[nxt] = now; 18 if (p == 0) Suf[now].pre = root; 19 else 20 { 21 int q = Suf[p].s[nxt]; 22 if (step[q] == step[p] + 1) Suf[now].pre = q; 23 else 24 { 25 int nq = ++cnt; 26 step[nq] = step[p] + 1; 27 Suf[nq] = Suf[q]; 28 Suf[q].pre = Suf[now].pre = nq; 29 for ( ; p != 0 && Suf[p].s[nxt] == q; p = Suf[p].pre) Suf[p].s[nxt] = nq; 30 } 31 } 32 last = now; 33 } 34 35 bool cmp(int a,int b) { return step[a] < step[b]; } 36 37 int main() 38 { 39 scanf("%s\n",S+1); 40 len1 = strlen(S+1); 41 for (i = 1; i <= len1; i++) add(S[i]-'a'); 42 43 for (i = 1; i <= cnt; i++) f[i] = i; 44 stable_sort(f+1,f+1+cnt,cmp); 45 46 memcpy(ans,step,sizeof(ans)); 47 48 while (scanf("%s\n",T+1) != EOF) 49 { 50 memset(nans,0,sizeof(nans)); 51 52 len2 = strlen(T+1); 53 int now = root,len = 0; 54 for (i = 1; i <= len2; i++) 55 { 56 int nxt = T[i]-'a'; 57 if (Suf[now].s[nxt] != 0) 58 { 59 len++; 60 now = Suf[now].s[nxt]; 61 nans[now] = max(nans[now],len); 62 } 63 else 64 { 65 while (Suf[now].s[nxt] == 0 && now != 0) now = Suf[now].pre; 66 if (now == 0) now = root,len = 0; 67 else len = step[now] + 1,now = Suf[now].s[nxt],nans[now] = max(nans[now],len); 68 } 69 } 70 for (i = cnt; i >= 1; i--) 71 { 72 ans[f[i]] = min(ans[f[i]],nans[f[i]]); 73 nans[Suf[f[i]].pre] = max(nans[Suf[f[i]].pre],nans[f[i]]); 74 } 75 } 76 77 int ANS = 0; 78 for (i = 1; i <= cnt; i++) 79 ANS = max(ANS,ans[i]); 80 81 printf("%d\n",ANS); 82 return 0; 83 }
posted on 2015-01-11 15:05 MMMoonLighttt 阅读(224) 评论(0) 编辑 收藏 举报