Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3
abcb
bca
acbc
Sample Output
2
HINT
Source
.
把第一个串建后缀自动机
然后拿其它串在上面跑,记录每个串匹配到这个点的最大长度,然后在parent树上保存子树最小值(还有和val取min),然后对于所有串取最大值…
说的简单,代码…
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int SZ = 100010;
const int INF = 1000000010;
struct sam_node{
sam_node *ch[30],*par;
int val,ans[5];
}T[SZ], *root, *last;
int Tcnt = 0;
sam_node* newnode(int x)
{
sam_node *k = T + (Tcnt ++);
k -> val = x;
memset(k -> ch,0,sizeof(k -> ch));
k -> par = 0;
memset(k -> ans,0,sizeof(k -> ans));
return k;
}
void insert(int x)
{
sam_node *p = last,*np = newnode(last -> val + 1);
while(p && !p -> ch[x])
p -> ch[x] = np,p = p -> par;
if(!p)
np -> par = root;
else
{
sam_node *q = p -> ch[x];
if(q -> val == p -> val + 1)
np -> par = q;
else
{
sam_node *nq = newnode(p -> val + 1);
memcpy(nq -> ch,q -> ch,sizeof(nq -> ch));
nq -> par = q -> par;
q -> par = np -> par = nq;
while(p && p -> ch[x] == q)
p -> ch[x] = nq,p = p -> par;
}
}
last = np;
}
void find(char s[],int id)
{
int l = strlen(s);
sam_node *p = root;
for(int i = 0,len = 0;i < l;i ++)
{
int c = s[i] - 'a' + 1;
if(p -> ch[c])
{
len ++;
p = p -> ch[c];
}
else
{
while(p != root && !p -> ch[c])
p = p -> par;
len = p -> val;
if(p -> ch[c])
p = p -> ch[c],len ++;
}
p -> ans[id] = max(p -> ans[id],min(p -> val,len));
}
for(int i = Tcnt - 1;i >= 1;i --)
{
sam_node *k = T + i;
k -> par -> ans[id] = min(k -> par -> val,max(k -> par -> ans[id],k -> ans[id]));
}
}
void init()
{
root = newnode(0);
last = root;
}
int n;
int dfs(sam_node *p)
{
int ans = INF;
for(int i = 1;i < n;i ++)
ans = min(ans,p -> ans[i]);
for(int i = 1;i <= 26;i ++)
if(p -> ch[i])
ans = max(ans,dfs(p -> ch[i]));
return ans;
}
char s[SZ];
int main()
{
init();
scanf("%d",&n);
scanf("%s",s);
int l = strlen(s);
for(int i = 0;i < l;i ++)
insert(s[i] - 'a' + 1);
for(int i = 1;i < n;i ++)
{
scanf("%s",s);
find(s,i);
}
printf("%d",dfs(root));
return 0;
}
/*
3
abdab
dab
abd
*/