hdu1711 kmp

把O(N*M)立减到O(N+M)的匹配算法,有没有好厉害的样子!结果next数组什么的,看的时候简直醉了。。

鉴于1711纯裸,那就借这个说说~也不知道自己到底有木有懂==


题意即给出两串数字,暂叫他a串和b串吧~要求输出b串与a串开始匹配的位置

比如那个样例

1 2 1 2 31 2 3 1 3 2 1 2

1 2 3 1 3

从第6位开始,所以输出6

当然很简单呀,两个循环一位一位比下去不就得了?

看这范围1 <= M <= 10000, 1 <= N <= 1000000,Time Limit: 10000/5000 MS (Java/Others),还敢暴力吗?


kmp基本思想就是把用不着重复比较的部分跳过去

bf的第二轮:

1 2 1 2 31 2 3 1 3 2 1 2

1 2 3 1 3

kmp的第二轮:

1 2 1 2 31 2 3 1 3 2 1 2

1 2 3 1 3

嗯,其实那个2完全可以直接跳过是把~

所以感觉kmp就是找出应该跳过哪一些,这就是通过next数组实现的~

void getnext(int *b,int *next)
{
    next[0]=next[1]=0;
    for(int i=1;i<M;i++)
    {
        int j=next[i];
        while(j&&b[i]!=b[j])
            j=next[j];
        next[i+1]=(b[i]==b[j]?j+1:0);
    }
}

这个next其实相当于在比较之前就已经初始化好了,计算嘛,是根据什么前缀后缀是否一样来的,详细解释篇幅会很多诶,反正网上资料很多哒~

嗯,next初始化好了,就要开始比较了,如何机智的避开不需要比较的那些元素呢?

int kmp(int *a,int *b,int *next)
{
    getnext(b,next);

    int j=0;
    for(int i=0;i<N;i++)
    {
        while(j&&a[i]!=b[j])
            j=next[j];
        if(a[i]==b[j])
            j++;
        if(j==M)
        {
            return i+1-M+1;
        }
    }
    return -1;
}

i,j还是俩指针,跳着指

嗯,就是这样,鉴于标题,再发个1711的主函数~

int main()
{
    int T;
    int po;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(next,0,sizeof(next));
        scanf("%d%d",&N,&M);
        //if(N<M){printf("-1\n");continue;}
        for(int i=0;i<N;i++)
            scanf("%d",&a[i]);
        for(int j=0;j<M;j++)
            scanf("%d",&b[j]);
        po=kmp(a,b,next);
        printf("%d\n",po);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值