[模板]KMP

题目描述

如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。

为了减少骗分的情况,接下来还要输出子串的前缀数组next。

(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)

输入格式

第一行为一个字符串,即为s1

第二行为一个字符串,即为s2

输出格式

若干行,每行包含一个整数,表示s2在s1中出现的位置

接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。

输入输出样例

输入 #1
ABABABC
ABA
输出 #1
1
3
0 0 1 

说明/提示

时空限制:1000ms,128M

数据规模:

设s1长度为N,s2长度为M

对于30%的数据:N<=15,M<=5

对于70%的数据:N<=10000,M<=100

对于100%的数据:N<=1000000,M<=1000000

 

 

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int next[1100000],n,m,j;
char a[1100000],b[1100000];
inline void getnext()
{
    int m=strlen(b+1),pos=-1;//虽然从一开始,但pos=-1.如果pos=0,导致next全体加一 
    next[0]=-1;
    for(int i=1;i<=m;i)//但是,i从一开始,所以pos右移1 
    {
        if(pos==-1||b[pos+1]==b[i])//因为next>=0,所以pos=-1 
        {
            pos++;
            next[i]=pos;
            i++;
        }
        else pos=next[pos];
    }
}
inline void kmp()
{
    int n=strlen(a+1),m=strlen(b+1);
    int posa=1,posb=0;
    for(posa=1;posa<=n;posa++)
    {
        while(posb&&a[posa]!=b[posb+1]) posb=next[posb];
        if(a[posa]==b[posb+1]) posb++;
        if(posb==m) printf("%d\n",posa-posb+1);
    }
}
int main()
{
    scanf("%s%s",a+1,b+1);
    int n=strlen(a+1),m=strlen(b+1);
    getnext();
    kmp();
    for(int i=1;i<=m;i++)
    {
        printf("%d ",next[i]);
    }
}

 

posted @ 2019-11-29 21:01  satans  阅读(158)  评论(0)    收藏  举报