Bazinga
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1472 Accepted Submission(s): 459
Problem Description
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
2000 letters.
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
ccc
Sample Output
Case #1: 4
Case #2: -1
Case #3: 4
Case #4: 3
解题思路:在写这题时需要用到匹配算法,一般想到节省时间的就是用kmp,但在c++中提供了一个函数
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。所以用这个函数更为方便。这题需要剪枝否则会超时。剪枝:首先对每对相邻的子串进行判断,如果编号小的字符串是编号大的字符串的子串,那么该编号小的字符串在后续的判断中无需出现了。接着就从最后一个字符串开始扫描判断就OK了。
#include<stdio.h>
#include<string.h>
char s[510][2005];
int num[510];
int main(){
int t,n,i,j,k;
k=1;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",s[i]);
}//输入
int v=-1;
memset(num,0,sizeof(num));
for(i=1;i<n;i++){
if(strstr(s[i+1],s[i])!=NULL){
num[i]=1;
}
}//剪枝
for(i=n;i>=2;i--){
for(j=i-1;j>=1;j--){
if(num[j])continue;
int l1=strlen(s[i]);
int l2=strlen(s[j]);
if(l1<l2)continue;
if(strstr(s[i],s[j])==NULL){
v=i;
break;
}
}
if(v!=-1)break;
}
printf("Case #%d: %d\n",k++,v);
}
return 0;
}