http://www.elijahqi.win/archives/2857
题意翻译
题面描述 给定一些字符串,求出它们的最长公共子串 输入格式 输入至多
10
10 行,每行包含不超过
100000
100000 个的小写字母,表示一个字符串 输出格式 一个数,最长公共子串的长度 若不存在最长公共子串,请输出
0
0 。
题目描述
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.
输入输出格式
输入格式:
The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.
输出格式:
The length of the longest common substring. If such string doesn’t exist, print “0” instead.
输入输出样例
输入样例#1: 复制
alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa
输出样例#1: 复制
2
求多个串的最长公共子串 首先针对第一个串建立sam 设mx[x]表示所有串在这个节点匹配的最长距离是多少 tmp[x]表示当前这个串和第一个串在该节点的最长匹配是多少
因为一次匹配不可能更新所有的tmp值所以我们需要在匹配之后拓扑排序之后 因为父节点肯定是当前节点的后缀所以匹配长度不会减少 然后每次更新完tmp之后再去更新mx
len[fa[p]]
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
char s[N];int n,len[N<<1],fa[N<<1],cnt=1,root=1,last=1;
int c[N],tmp[N<<1],mx[N<<1],ans,ch[N<<1][26],rk[N<<1];
inline void insert1(int x){
int np=++cnt,p=last;len[np]=len[p]+1;
for (;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if (!p) fa[np]=root;else{
int q=ch[p][x];if (len[p]+1==len[q]) fa[np]=q;else{
int nq=++cnt;fa[nq]=fa[q];memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=fa[np]=nq;len[nq]=len[p]+1;for (;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}last=np;
}
int main(){
freopen("spoj1812.in","r",stdin);
scanf("%s",s+1);n=strlen(s+1);
for (int i=1;i<=n;++i) insert1(s[i]-'a');
for (int i=1;i<=cnt;++i) ++c[len[i]];
for (int i=1;i<=n;++i) c[i]+=c[i-1];memset(mx,0x3f,sizeof(mx));
for (int i=cnt;i;--i) rk[c[len[i]]--]=i;
while(~scanf("%s",s+1)){int m=strlen(s+1);
memset(tmp,0,sizeof(tmp));int now=1,l=0;
for (int i=1;i<=m;++i){
if (ch[now][s[i]-'a']) ++l,now=ch[now][s[i]-'a'];
else{
while(now&&!ch[now][s[i]-'a']) now=fa[now];
if (!now) now=1,l=0;else l=len[now]+1,now=ch[now][s[i]-'a'];
}tmp[now]=max(tmp[now],l);
}
for (int i=cnt;i;--i){
int x=rk[i];mx[x]=min(mx[x],tmp[x]);
if(fa[x]&&tmp[x]) tmp[fa[x]]=len[fa[x]];
}
}for (int i=1;i<=cnt;++i) ans=max(ans,mx[i]);printf("%d\n",ans);
return 0;
}