1. 程式人生 > >Bazinga HDU

Bazinga HDU

Ladies and gentlemen, please sit up straight. 
Don't tilt your head. I'm serious. 

For nn given strings S1,S2,,SnS1,S2,⋯,Sn, labelled from 11 to nn, you should find the largest i(1in)i (1≤i≤n) such that there exists an integer j(1j<i)j (1≤j<i) and SjSj is not a substring of SiSi

A substring of a string SiSi is another string that occurs in
 SiSi. For example, ``ruiz" is a substring of ``ruizhang", and ``rzhang" is not a substring of ``ruizhang". InputThe first line contains an integer t(1t50)t (1≤t≤50) which is the number of test cases. 
For each test case, the first line is the positive integer n(1n500)n (1≤n≤500) and in the following n
n
 lines list are the strings S1,S2,,SnS1,S2,⋯,Sn
All strings are given in lower-case letters and strings are no longer than 20002000letters. OutputFor each test case, output the largest label you get. If it does not exist, output 1−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
因為是找最大值所以從後往前找哪個不是他的子串,那麼正常想法就是從第一個開始判斷了,但是那樣複雜度會過高。
所以對字串進行預處理,如果第I個字串和第i+1個匹配, 就把mark【i】置為1.
這樣,對於一個字串,當判斷前面的字串是不是他的子串時,可以先判斷mark[j]是否為1,因為如果為一說明他是(j+1)的子串,就判斷(j+1)與母串關係就好了。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[505][2005];
int mark[505];
int n[505][2005];
void kmp(int i)
{
    n[i][0]=-1;
    int k=-1;
    int j=0;
    int len=strlen(s[i]);
    while(j<len)
    {
        if(k==-1||s[i][j]==s[i][k])
        {
            k++;
            j++;
            n[i][j]=k;
        }
        else k=n[i][k];
    }
}

int match(char *a,char *b,int x)
{
     int len1=strlen(a),len2=strlen(b);
        //kmp(len1);
        int flag=0;
        for(int i=0,j=0;i<len2;i++)
        {
            while(j>0&&a[j]!=b[i])j=n[x][j];
            if(a[j]==b[i])j++;
            if(j==len1){flag++;break;}
        }
       if(flag)
       {

           return 1;
       }
       else return 0;
}
int main()
{
    int n;
    int t;
    cin>>t;
    int z=1;
    while(t--)
    {
        scanf("%d",&n);
        memset(mark,0,sizeof(mark));
        getchar();
        for(int i=0;i<n;i++)
        {
            scanf("%s",s[i]);
            kmp(i);
        }
        int ans=0;
        for(int i=0;i<n-1;i++)
        {

           mark[i]=match(s[i],s[i+1],i);
        }
     
        int mmax=0;
       for(int i=n-1;i>=0;i--)
       {
               for(int j=0;j<i;j++)
               {
                   if(mark[j]==1)
                    continue;
                   else
                    {
                        if(!match(s[j],s[i],j))
                        {
                            mmax=i+1;
                            break;
                        }
                    }

               }
                  if(mmax!=0)break;
           }
           printf("Case #%d: ",z++);
            if(mmax==0)printf("-1\n");
            else printf("%d\n",mmax);
    }
    return 0;
}