HDU5510 Bazinga KMP+剪枝

这道题,很蛋疼,放了两个星期捡起来,用之前wrong answer的代码重新提交一遍竟然报TLE了!

我顿时不淡定了。

重新检查了KMP模版,搜了题解,发现一个超diao的函数  strstr ( char *a , char *b),判断b是不是a的字串,其速度竟比KMP还快,据说最新的strstr是用传说中的 TWO WAY方式写的。以后比赛还用的上kmp么,我只能说两手准备吧。

思路还是很简单,直接两个for循环利用kmp,加上一个简单的剪枝(这个剪枝。。。有点无语,感觉没什么卵用,但是不加就是会超时)

看代码。

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
char s[505][2005];
int f[2005];
void preKmp(char x[],int m,int kmpNext[])
{
    int i,j;
    j=kmpNext[0]=-1;
    i=0;
    while(i<m)
    {
        while(-1!=j && x[i]!=x[j])
            j=kmpNext[j];
        if(x[++i]==x[++j])
            kmpNext[i]=kmpNext[j];
        else
            kmpNext[i]=j;
    }
}
int find(char x[],int m, char y[],int n)
{
    int i,j;
    preKmp(x,m,f);
    i=j=0;
    while(i<n)
    {
        while(j!=-1 && y[i]!=x[j] )
            j=f[j];
        i++;j++;
        if(j==m)
           return 0;
    }
    return 1;
}
int main()
{
    int T,n,i,j,m,n1,cas=0,ans,vis[505];
    scanf("%d",&T);
    while(T--)
    {
        cas++;
        scanf("%d",&n);
        ans=-1;
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++)
        {
            scanf("%s",s[i]);
            for(j=1;j<i;j++)
            {
                if(vis[j]) continue;   //如果s[j] 是j之后的某个串A的字串,则不必再检查s[j],因为不存在s[j]不是B的子串而A是B的子串的情况
                m=strlen(s[j]);<span style="white-space:pre">							</span>
                n1=strlen(s[i]);
                if(find(s[j],m,s[i],n1))
              //  if(strstr(s[i],s[j])==NULL)   //这个跑出来最快是327ms,KMP最快是707ms。
                {
                    ans=i;
                    break;
                }
                else
                    vis[j]=1;
            }
        }
        printf("Case #%d: %d\n",cas,ans);
    }
    return 0;
}


你可能感兴趣的:(HDU5510 Bazinga KMP+剪枝)