这道题是我出的啦。。
一开始是给小朋友做得暴力题。。于是我改造了一下。。
题解
其实并不是什么难题。。
一开始的时候是作为后缀数组出的啦,本来是想二分答案的
然后乱搞。。
接着因为没人验题,于是到考试那天才发现不满足二分性。。于是就把数据都调弱了,二分变成for了。。
这个方法在这个数据期望30分吧。。
然后正解,我只想到了后缀自动机,你就建广义的。。
然后将right集合的求法稍微改一改就知道出现在多少个串里了
然后就可以线性出解了,感觉很优越啊,这个方法!!
#include<cstdio>
#include<cstring>
const int N=560*1005;
struct qq{int son[26],pre,step,lalal;}s[N];
int last,tot;
int n,m;
int vis[N],cnt;
void ins (int x)
{
int np=++tot,p=last;
s[np].step=s[p].step+1;
while (p!=0&&s[p].son[x]==0) s[p].son[x]=np,p=s[p].pre;
if (p==0) s[np].pre=1;
else
{
int q=s[p].son[x];
if (s[q].step==s[p].step+1) s[np].pre=q;
else
{
int nq=++tot;
s[nq]=s[q];
s[nq].step=s[p].step+1;
s[q].pre=s[np].pre=nq;
while (p!=0&&s[p].son[x]==q) s[p].son[x]=nq,p=s[p].pre;
}
}
last=np;
}
int mymax (int x,int y)
{
return x>y?x:y;
}
int main()
{
memset(vis,0,sizeof(vis));cnt=0;
tot=1;
scanf("%d%d",&n,&m);
for (int u=1;u<=n;u++)
{
cnt++;
int Last=tot+1;
last=1;
char ch=getchar();
while (ch<'a'||ch>'z') ch=getchar();
while (ch>='a'&&ch<='z') ins(ch-'a'),ch=getchar();
for (int i=Last+1;i<=tot;i++)
{
int x=i;
while (x!=0&&vis[x]!=cnt)
vis[x]=cnt,s[x].lalal++,x=s[x].pre;
}
}
int ans=0;
for (int u=1;u<=tot;u++)
if (s[u].lalal==m)
ans=mymax(ans,s[u].step);
printf("%d\n",ans);
return 0;
}