Bazinga HDU - 5510

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

For  n n given strings  S1,S2,,Sn S1,S2,⋯,Sn, labelled from  1 1 to  n n, 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  Sj Sj is not a substring of  Si Si

A substring of a string  Si Si is another string that occurs  in  Si 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) 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,,Sn S1,S2,⋯,Sn
All strings are given in lower-case letters and strings are no longer than  2000 2000letters.
Output
For 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值