HDU (1711) first kmp

http://acm.hdu.edu.cn/showproblem.php?pid=1711
#include<bits/stdc++.h>
using namespace std;

#define maxn 1000005
int str[maxn];
int son[maxn];
int net[maxn];
int m,n;
void getnext()
{
    int j=0,k=-1;
    net[0]=-1;
    while(j<m)
    {
        //son[k]表示前缀,son[j]表示后缀。
        //比如字串是12211
        //第一次会更新为next[1]=0;
        //第二次会不更新next而是去把k回到next[0]=-1;
        //此时第一个最小的子子串检查完毕重新回到起点第三次会更新为next[2]=0,然后k又回到next[0]=-1;
        //所以此时它会到达next[3]=0;
        //然后再一次进行判断这时会有后缀前缀相同next[j]=k;
        if(k==-1||son[j]==son[k])
        {
            j++;
            k++;
            net[j]=k;//初始化next数组 next数组为下标对应着字串的下标,里面存 的值对应着 ,
            //字串到这个位置的为止的那部分字符串最大前缀与最大后缀相等的字符数 ,
        }
        else
            k=net[k];
    }
}
int kmp()
{
    int i=0,j=0;
    getnext();
    while(i<n)
    {
        //i主串的i一直在增加。
        //但是j会随着kmp算法的优化根据前后缀相等的部分通过next数组进行缩短处理 。
        if(j==-1||str[i]==son[j])
        {
            i++;
            j++;
        }
        else
            j=net[j];//通过next数组优化过程 。
        if(j==m)//找到字串停止。
            return i;
    }
    return -1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            scanf("%d",&str[i]);
        for(int i=0; i<m; i++)
            scanf("%d",&son[i]);
        if(kmp()==-1)
            printf("-1\n");
        else
            printf("%d\n",kmp()-m+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/beposit/article/details/80673188