Ladies and gentlemen, please sit up straight.
Don't tilt your head. I'm serious.For n given strings S1,S2,⋯,Sn, labelled from 1 to n, you should find the largest i (1≤i≤n) such that there exists an integer j (1≤j<i) and Sj is not a substring of Si.
A substring of a string Si is another string that occurs in Si
. For example, ``ruiz" is a substring of ``ruizhang", and ``rzhang" is not a substring of ``ruizhang".
Input The first line contains an integer t (1≤t≤50) which is the number of test cases. For each test case, the first line is the positive integer n (1≤n≤500) and in the following n lines list are the strings S1,S2,⋯,Sn.
All strings are given in lower-case letters and strings are no longer than 2000letters. Output For each test case, output the largest label you get. If it does not exist, output −1. Sample Input
4 5 ab abc zabc abcd zabcd 4 you lovinyou aboutlovinyou allaboutlovinyou 5 de def abcd abcde abcdef 3 a ba cccSample Output
Case #1: 4 Case #2: -1 Case #3: 4 Case #4: 3
题意:给定n个串,求最大的下表i使得在1~i-1中至少有一个串不是其子串
思路: 暴力O(T*n*n*(n+m)) 于是TLE
优化~用l代表对于当前i,所能抵达的l。如果s[l]不是s[i]的字串,break。 如果是,l++;
#include <stdio.h>
#include <string.h>
typedef long long ll;
using namespace std;
const int N=2e3+5;
char s[501][N];
int next[N];
int lena,lenb;
char a[N];
char b[N];
ll ans;
void set_naxt()
{
int i=0,j=-1;
next[0]=-1;
while(i<lenb)
{
if(j==-1||b[i]==b[j])
{
i++; j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp()
{
int i=0,j=0;
set_naxt();
while(i<lena)
{
if(j==-1||a[i]==b[j])
{
i++;j++;
}
else
j=next[j];
if(j==lenb)
{
return 1;
}
}
return 0;
}
int main(void){
int T;
int ks=1;
scanf("%d",&T);
while(T--){
ans=-1;
int m;
scanf("%d",&m);
register int i,l=1;
bool flag=true;
for(i=1;i<=m;i++) scanf("%s",s[i]);
for(i=1;i<=m;i++){
while(l<i){
strcpy(a,s[i]),strcpy(b,s[l]);
lena=strlen(a),lenb=strlen(b);
if(kmp()==1) l++;
else {ans=i;break;}
}
}
printf("Case #%d: %d\n",ks++,ans);
}
}