[HDU 5510][2015ACM/ICPC 亚洲区沈阳站] Bazinga KMP+剪支

Bazinga
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1597 Accepted Submission(s): 499

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

A substring of a string Si is another string that occurs in Si. For example, ruiz" is a substring ofruizhang”, and rzhang" is not a substring ofruizhang”.

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
2015ACM/ICPC亚洲区沈阳站-重现赛

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510

题意
一些字符串,问下标最大的字符串使得下标小于它的字符串中存在一个字符串不是它的子串(连续)

思路
n^2+kmp肯定超时,剪支可吧被匹配上的串删掉,保证后面的能匹配上的(无所谓),!kmp的没被删去;满足条件的break掉搜下面串即可;

if(kmp(i,j))   vis[j]=1;
else    flag=1ans=ibreak;                 

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char s[502][2002];
int flag;
int vis[502];
int ans;
int nex[502][2002];
void pre(char ss[],int id)
{
    int j=-1;
    for(int i=0;ss[i];i++)
    {
        while(ss[i]!=ss[j+1]&&j!=-1)
        {
            j=nex[id][j];
        }
        if(ss[i]==ss[j+1]&&i!=0) j++;
        nex[id][i]=j;
    }
}
bool kmp(int x,int y)
{
    int j=-1;
    for(int i=0;s[x][i];i++)
    {
        while(s[x][i]!=s[y][j+1]&&j!=-1) j=nex[y][j];
        if(s[x][i]==s[y][j+1]) j++;
        if(j==strlen(s[y])-1) return 1;
    }
    return 0;
}
int T,n;
int main()
{
    scanf("%d",&T);
    int cnt=0;
    while(T--)
    {
        cnt++;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {

            scanf("%s",s[i]);
            pre(s[i],i);
            vis[i]=0;
        }
        flag=0;
        for(int i=2;i<=n;i++)
        {
            for(int j=i-1;j>=1;j--)
            if(!vis[j])
            {
                if(kmp(i,j))
                {

                    vis[j]=1;
                }
                else 
                {
                    flag=1;
                    ans=i;
                    break;
                }
            }
        }
        printf("Case #%d: ",cnt);
        if(flag)
        printf("%d\n",ans);
        else printf("-1\n");

    }


}

你可能感兴趣的:(KMP,ACM,HDU)