HDU 5510 Bazinga

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
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
 
Source

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

这说明了什么?这说明如果A是B的子串,那么A就没用了,这就是一个除去冗余的数据的过程,接下来就是暴力了。由于题目的要求是它之前的必须是它的子串,所以,只要比较相邻的串即可除去冗余的串

 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
",cs++,ret);
40     }
41     return 0;
42 }
View Code
原文地址:https://www.cnblogs.com/crackpotisback/p/4925990.html