题目大意
有n个字符串,求编号最大的字符串,它前面有一个串不是它的子串。
解题思路
顺序枚举当前字符串now,维护一个指针表示最前一个不是当前串的子串的串,可以发现如果当前串是后面串的子串,前面的串也一定是后面串的子串,每个串都只考虑一次,所以复杂度是可以的。
code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=
500,maxl=
2000;
int t,n,len[maxn+
10],fail[maxl+
10];
char s[maxn+
10][maxl+
10];
bool cmp(
int x,
int y){
if(len[x]>len[y])swap(x,y);
fo(i,
2,len[x]){
fail[i]=fail[i-
1];
for(;fail[i]&&(s[x][i]!=s[x][fail[i]+
1]);fail[i]=fail[fail[i]]);
fail[i]+=(s[x][i]==s[x][fail[i]+
1]);
}
int now=
0;
fo(i,
1,len[y]){
for(;now&&(s[y][i]!=s[x][now+
1]);now=fail[now]);
now+=(s[y][i]==s[x][now+
1]);
if(now==len[x])
return 1;
}
return 0;
}
int main(){
freopen(
"sub.in",
"r",stdin);
freopen(
"sub.out",
"w",stdout);
scanf(
"%d",&t);
fo(cas,
1,t){
scanf(
"%d",&n);
int ans=-
1,now=
1;
fo(i,
1,n){
scanf(
"%s",s[i]+
1);len[i]=
strlen(s[i]+
1);
for(;(now!=i)&&(cmp(now,i));now++);
if(now!=i)ans=i;
}
printf(
"%d\n",ans);
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-970045.html