Bazinga

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 101    Accepted Submission(s): 41

Problem Description

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
5
de
def
abcd
abcde
abcdef
3
a
ba
ccc

Sample Output
Case #1: 4
Case #2: -1
Case #3: 4
Case #4: 3

Source

解题：KMP暴力搞，如果A是B的子串，B是C的子串，那么A一定是C的子串。如果B不是C的子串，A有可能是C的子串。

 1 #include <bits/stdc++.h>
2 using namespace std;
3 const int maxn = 2010;
4 int fail[maxn];
5 void getFail(char str[]) {
6     for(int i = 0,j = fail[0] = -1; str[i]; ++i) {
7         while(j != -1 && str[i] != str[j]) j = fail[j];
8         fail[i + 1] = ++j;
9     }
10 }
11 bool match(char sa[],char sb[]) {
12     getFail(sa);
13     for(int i = 0,j = 0; sb[i]; ++i) {
14         while(j != -1 && sb[i] != sa[j]) j = fail[j];
15         if(!sa[++j]) return true;
16     }
17     return false;
18 }
19 char S[501][maxn];
20 bool invalid[501];
21 int main() {
22     int kase,n,cs = 1;
23     scanf("%d",&kase);
24     while(kase--) {
25         scanf("%d",&n);
26         memset(invalid,false,sizeof invalid);
27         for(int i = 0; i < n; ++i) {
28             scanf("%s",S[i]);
29             if(i && match(S[i-1],S[i]))
30                 invalid[i-1] = true;
31         }
32         int ret = -1;
33         for(int i = n-1; i >= 0 && ret == -1; --i) {
34             for(int j = 0; j < i && ret == -1; ++j) {
35                 if(invalid[j]) continue;
36                 if(!match(S[j],S[i])) ret = i + 1;
37             }
38         }
39         printf("Case #%d: %d\n",cs++,ret);
40     }
41     return 0;
42 }
View Code