Description
Input
Sample Input
4
5
ab
abc
zabc
abcd
zabcd
4
you
lovinyou
aboutlovinyou
allaboutlovinyou
5
de
def
abcd
abcde
abcdef
3
a
ba
ccc
Output
Sample Output
4
-1
4
3
Data Constraint
Solution
我们第一眼可以想到对于每一个串都使用KMP逐一匹配
那么时间复杂度将是 O(T⋅N2⋅S) ,明显超限!
继续思考,知道性质:对于三个串:a,b,c;
a是b的子串,b是c的子串;
那么a也会是c的子串!
于是我们想到优化,枚举相邻的两个子串,判断是否是子串
如果是,那么就不需要处理,继续枚举!
如果不是,那么就从下往上对于这个串进行一次逐一比对
再加上是否大于Ans的剪枝优化
时间复杂度可以接近 O(T⋅N⋅S) ,成功AC!
Code
#include<cstdio>
#include<cstring>
using namespace std;
const int N=501,M=2002;
int ans,n;
int a[N],next[N][M];
char s[N][M];
inline int read()
{
int data=0; char ch=0;
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
return data;
}
inline void init()
{
n=read();
ans=0;
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
a[i]=strlen(s[i]+1);
for(int j=2,k=0;j<=a[i];j++)
{
while(k && s[i][j]!=s[i][k+1]) k=next[i][k];
if(s[i][j]==s[i][k+1]) k++;
next[i][j]=k;
}
}
}//KMP的预处理
inline void work()
{
for(int k=n;k>1 && k>ans;k--)
{
bool bz=false;
for(int i=1,j=0;i<=a[k];i++)
{
while(j && s[k][i]!=s[k-1][j+1]) j=next[k-1][j];
if(s[k][i]==s[k-1][j+1]) j++;
if(j==a[k-1])
{
bz=true;
break;
}
}//两两配对
if(!bz)
{
if(k>ans) ans=k;
for(int p=n;p>k && p>ans;p--)
{
bz=false;
for(int i=1,j=0;i<=a[p];i++)
{
while(j && s[p][i]!=s[k-1][j+1]) j=next[k-1][j];
if(s[p][i]==s[k-1][j+1]) j++;
if(j==a[k-1])
{
bz=true;
break;
}
}
if(!bz)
{
if(p>ans) ans=p;
break;
}
}//逐一配对
}
}
if(!ans) printf("-1\n"); else printf("%d\n",ans);
}
int main()
{
int T=read();
while(T--)
{
init();
work();
}
return 0;
}