Description
FGD的眼睛瞪得像苹果,他还计划中午回到母舰去他家旁边的咖啡厅去喝一杯呢。看来咖啡是暂时泡汤了。
“据说,为了预防日益增加的逃兵问题,这战机的引擎没有舰长的命令,是无法关闭,只能向前的。”
“好!现在我下令让他关闭!”
“可是,我们都不知道该怎么关掉他。”
……
FGD走到动力舱,一脚踢开在控制台上焦头烂额的工程师,自己坐了上去。
一小时后……
FGD发现每当他想关闭引擎的时候,就会有一大堆乱码跳出来,他便会不由自主地去阅读那一大段无规律的文字,阻止他的正常思维,使得他没有空闲时间去按下对话框的确定。
一天后……
FGD终于有点头绪了,他发现这段文字并不是完全漫无规律的,这段仅仅由小写字母组成的文字可以被分为长度相同的若干行,每行都有一串相同的连续的文字,隐藏在其他乱码中间。FGD以他敏锐的大脑相信,那段最长的被重复的文字一定包含有惊天的大秘密。现在你帮忙告诉他那段文字的长度吧。
Input
输入文件第一行为两个整数n和l,表示这段文字共可以分为n行,每行的长度均为l。(1<=n<=10,1<=l<=10000)
接下来n行为那n行仅有小写字母组成的文字。
Output
要求输出文件仅包含一行,一个整数,为这n行文字都包含的最长的一段连续的文字的长度。
Sample Input
2 5
ababc
cabac
Sample Output
3
HINT
思路
首先将几个串连在一起,然后把最长不重叠子串改一改就好了。
代码
#include <cstdio>
#include <algorithm>
const int maxn=300000;
char s[maxn+10],t[maxn+10];
int m,len,pos[maxn+10];
struct suffix_array
{
int rank[maxn+10],sa[maxn+10],sum[maxn+10],tmp[maxn+10],h[maxn+10];
inline int suffix_sort(int n)
{
int m=127,p=1,len=1;
int* x=rank;
int* y=tmp;
for(register int i=1; i<=n; ++i)
{
x[i]=s[i];
y[i]=i;
++sum[x[i]];
}
for(register int i=1; i<=m; ++i)
{
sum[i]+=sum[i-1];
}
for(register int i=n; i; --i)
{
sa[sum[x[i]]]=i;
--sum[x[i]];
}
while(p<n)
{
m=p;
p=0;
for(register int i=0; i<=m; ++i)
{
sum[i]=0;
}
for(register int i=n-len+1; i<=n; ++i)
{
++p;
y[p]=i;
}
for(register int i=1; i<=n; ++i)
{
if(sa[i]-len>0)
{
++p;
y[p]=sa[i]-len;
}
}
for(register int i=1; i<=n; ++i)
{
++sum[x[y[i]]];
}
for(register int i=1; i<=m; ++i)
{
sum[i]+=sum[i-1];
}
for(register int i=n; i; --i)
{
sa[sum[x[y[i]]]]=y[i];
--sum[x[y[i]]];
}
std::swap(x,y);
p=1;
x[sa[1]]=1;
for(register int i=2; i<=n; ++i)
{
if(!((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+len]==y[sa[i-1]+len])))
{
++p;
}
x[sa[i]]=p;
}
len<<=1;
}
p=0;
for(register int i=1; i<=n; ++i)
{
++p;
rank[sa[i]]=p;
}
return 0;
}
inline int get_height(int n)
{
int k=0;
for(register int i=1; i<=n; ++i)
{
if(k)
{
--k;
}
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k])
{
++k;
}
h[rank[i]]=k;
}
return 0;
}
inline int judge(int x,int n)
{
int b[11],cnt=1;
for(register int i=1; i<=m; ++i)
{
b[i]=0;
}
b[pos[sa[1]]]=1;
for(int i=2; i<=n; ++i)
{
if(h[rank[sa[i]]]<x)
{
for(register int j=1; j<=m; ++j)
{
b[j]=0;
}
cnt=1;
b[pos[sa[i]]]=1;
}
else if(!b[pos[sa[i]]])
{
b[pos[sa[i]]]=1;
++cnt;
}
if(cnt>=m)
{
return 1;
}
}
return 0;
}
inline int work(int n)
{
suffix_sort(n);
get_height(n);
int left=0,right=len;
while(left<=right)
{
int mid=(left+right)>>1;
if(judge(mid,n))
{
left=mid+1;
}
else
{
right=mid-1;
}
}
return left-1;
}
};
suffix_array sa;
int main()
{
scanf("%d%d",&m,&len);
int x=0;
for(register int i=1; i<m; ++i)
{
scanf("%s",t+1);
for(register int j=1; j<=len; ++j)
{
s[x+j]=t[j];
pos[x+j]=i;
}
x+=len+1;
s[x]='~';
}
scanf("%s",t+1);
for(register int i=1; i<=len; ++i)
{
s[x+i]=t[i];
pos[x+i]=m;
}
x+=len;
printf("%d\n",sa.work(x));
return 0;
}