您的位置:首页 > 产品设计 > UI/UE

hdu1711 Number Sequence---KMP

2013-11-21 21:04 344 查看
第一道KMP,真是费了好大劲才弄明白getnext的原理。但愿周末讲座我不会讲晕。

这是一道最简单的裸的KMP。

题意:给一个匹配串,一个模式串,问模式串是否在匹配串中出现过,若出现过,输出第一个匹配的位置,否则-1.

首先明白KMP的原理,重点是求next数组。

这里我学男神的方法是,next[i]=j 表示从 1 到 i 的串中,前缀和后缀最长匹配了 j 个长度。

求next:

1、显然next[1]=0

2、j 初始为 0 ,j 表示从 1 到 i-1 (包括 i-1)这个串中匹配了 j 个长度。

3、每次 i 和 j+1 比,若相等,j++,这个好理解。

若不相等,则从之前已经完全匹配好的 1到 j 中找 与 s[i] 相等的位置 j ,然后 j= next[j],这就利用到了之前完全匹配好的串。再接着从j+1开始匹配

如果一直都没有与 s[i] 相等的,那么 j=0,从头开始匹配了。

利用next来匹配:

基本想法和求next是一样的 只不过 i 变成了表示匹配串s1里的位置。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define mod 1000000009
using namespace std;

int t,m,n,s1[1000010],s2[10005],next[10005];

void getnext()
{
    int j,i;
    memset(next,0,sizeof next);
    j=0;
    for(i=2;i<=m;i++)
    {
        while(j>0&&s2[i]!=s2[j+1])
            j=next[j];
        if(s2[i]==s2[j+1])
            j++;
        next[i]=j;
    }
    //for(i=1;i<=m;i++)
   //     printf("i:%d nexti:%d\n",i,next[i]);
}

int cal()
{
    int i,j;
    j=0;
    for(i=1;i<=n;i++)
    {
        while(j>0&&s1[i]!=s2[j+1])//为什么j>0 因为i可能跟s2里面一个都匹配不了
        {
            j=next[j];
        }
        if(s1[i]==s2[j+1])
        {
            j++;
           // i++;
        }
        if(j==m)
        {
            return i-j+1;
        }
    }
    return -1;
}

int main()
{
    int i;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%d",&s1[i]);
        for(i=1;i<=m;i++)
            scanf("%d",&s2[i]);
        getnext();
        printf("%d\n",cal());
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: