SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS
Posted Meek
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS相关的知识,希望对你有一定的参考价值。
LCS2 - Longest Common Substring II
A string is finite sequence of characters over a non-empty finite set Σ.
In this problem, Σ is the set of lowercase letters.
Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.
Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.
Here common substring means a substring of two or more strings.
Input
The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.
Output
The length of the longest common substring. If such string doesn‘t exist, print "0" instead.
Example
Input: alsdfkjfjkdsal fdjskalajfkdsla aaaajfaaaa Output: 2
Notice: new testcases added
题意:
求多个串的最长公共字串
题解:
将第一个串建立后缀自动机
根据拓扑排序更新每个状态节点下所能向前延伸的长度,每次匹配一个串都更新即可
是不是很模糊
#include <bits/stdc++.h> inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}return x*f;} using namespace std; const int N = 3e5+7; const long long mod = 1000000007; int isPlus[N * 2],endpos[N * 2];int d[N * 2]; int tot,slink[2*N],trans[2*N][28],minlen[2*N],maxlen[2*N],pre; int newstate(int _maxlen,int _minlen,int* _trans,int _slink){ maxlen[++tot]=_maxlen;minlen[tot]=_minlen; slink[tot]=_slink; if(_trans)for(int i=0;i<26;i++)trans[tot][i]=_trans[i],d[_trans[i]]+=1; return tot; } int add_char(char ch,int u){ int c=ch-‘a‘,v=u; int z=newstate(maxlen[u]+1,-1,NULL,0); isPlus[z] = 1; while(v&&!trans[v][c]){trans[v][c]=z;d[z]+=1;v=slink[v];} if(!v){ minlen[z]=1;slink[z]=1;return z;} int x=trans[v][c]; if(maxlen[v]+1==maxlen[x]){slink[z]=x;minlen[z]=maxlen[x]+1;return z;} int y=newstate(maxlen[v]+1,-1,trans[x],slink[x]); slink[z]=slink[x]=y;minlen[x]=minlen[z]=maxlen[y]+1; while(v&&trans[v][c]==x){trans[v][c]=y;d[x]--,d[y]++;v=slink[v];} minlen[y]=maxlen[slink[y]]+1; return z; } void init_sam() { for(int i = 1; i <= tot; ++i) for(int j = 0; j < 26; ++j) trans[i][j] = 0; pre = tot = 1; } int dp[N],ans,n,vis[N],cnt[N],pos[N]; char a[N]; int main() { int f = 1; while(scanf("%s",a)!=EOF) { n = strlen(a); if(f) { init_sam(); for(int i = 0; i < n; ++i) pre = add_char(a[i],pre); f = 0; for(int i = 0; i <= n; ++i)cnt[i] = 0; for(int i = 2; i <= tot; ++i)cnt[maxlen[i]] += 1; for(int i = 1; i <= n; ++i)cnt[i]+=cnt[i-1]; for(int i = tot; i >= 2; --i)pos[cnt[maxlen[i]]--] = i; } else { int now = 1,sum = 0; for(int i = 0; i < n; ++i) { if(trans[now][a[i]-‘a‘]) { sum++; now = trans[now][a[i]-‘a‘]; dp[now] = max(dp[now],sum); } else { while(now) { now = slink[now]; if(trans[now][a[i]-‘a‘]) break; } if(!now) now = 1,sum = 0; else { sum = maxlen[now] + 1; now = trans[now][a[i]-‘a‘]; dp[now] = max(dp[now],sum); } } } for(int i = tot; i >= 2; --i) { int v = pos[i]; maxlen[v] = min(maxlen[v],dp[v]); dp[slink[v]] = max(dp[slink[v]],dp[v]); dp[v] = 0; } } } int ans = 0; for(int i = 2; i <= tot; ++i) { ans = max(ans,maxlen[i]); } printf("%d\n",ans); return 0; } /* aabbcd babbefg cdbbabb */
以上是关于SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS的主要内容,如果未能解决你的问题,请参考以下文章
刷题SPOJ 1812 LCS2 - Longest Common Substring II
spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)
●SPOJ LCS2Longest Common Substring II
SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS