Bazinga

Bazinga

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


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 (1in) such that there exists an integer j (1j<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 (1t50) which is the number of test cases.
For each test case, the first line is the positive integer n (1n500) 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
 
题目大意:
给你N个字符串,分别为S1,S2....Sn,让你求出存在最大的i(1 < = i <= n),使得Si与Sj不匹配(1< = j < i),输出这个i即可。
解法:如果直接用对每次i去和前面i-1个字符串匹配,那么复杂度为0(50*500*500*(2000+2000))会超时的。
首先,需要进行对其优化,因为要求的是最大的i,所以,我们可以从最后一个字符串往前面进行匹配。
其次,如果a<b,Sa是Sb的子串的话,我们可以把Sa合并到Sb里面,可以减少字符串的个数。
然后,就可以避免各自最复杂的情况,可以直接求解答案了、
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 struct Str{
 7     char Str[2010];
 8     int Next;//记录下一个字符串的编号
 9     int Fa;//记录上一个字符串的编号
10 }ID[555];
11 int Len;
12 void getNext(char p[],int next[],int Len_t)
13 {
14     int i=0,j=-1;
15     next[0]=-1;
16     while(i<Len_t){
17         if(j==-1||p[i]==p[j])next[++i]=++j;
18         else j=next[j];
19     }
20 }
21 int KMPMatch(char s[],char p[])
22 {
23     int next[200005];
24     int i=0,j=0,sign=0;
25     int Len_t=strlen(p),Len_S=strlen(s);
26     getNext(p,next,Len_t);
27     while(i<Len_S)
28     {
29         if(j==-1||s[i]==p[j]){i++;j++;}
30         else j=next[j];
31         if(j==Len_t) return i-Len_t+1;
32     }
33     return -1;    /*返回值是子串在主串第一个匹配的起始位置*/
34 }
35 int main()
36 {
37     int T,i,j,Ans,N,t=1;
38     scanf("%d",&T);
39     while(T--){
40         scanf("%d",&N);Ans=1;
41         ID[0].Next=1;
42         for(i=1;i<=N;i++){
43             scanf(" %s",ID[i].Str);
44             ID[i].Next=i+1;ID[i].Fa=i-1;
45         }
46         for(i=2;i<=N;i++){//合并字符串
47             int TMD=ID[i].Fa;
48             if(!TMD)continue;
49             if(KMPMatch(ID[i].Str,ID[TMD].Str)!=-1){
50                 ID[i].Fa=ID[TMD].Fa;
51                 ID[ID[TMD].Fa].Next=i;
52                 i--;
53             }
54         }
55         printf("Case #%d: ",t++);
56         for(i=N;i>=1&&Ans;i--){//从后面开始匹配
57             for(j=ID[i].Fa;j>0&&Ans;j=ID[j].Fa){//每次查找上一个不是其子串的字符串
58             if(KMPMatch(ID[i].Str,ID[j].Str)==-1){
59                     printf("%d\n",i);Ans=0;break;
60                 }
61             }
62         }
63         if(Ans)printf("-1\n");
64 
65     }
66     return 0;
67 }
View Code

 

 
posted @ 2016-04-20 21:31  Wurq  阅读(253)  评论(0编辑  收藏  举报