洛谷 P3375 【模板】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<=1000

样例说明:

所以两个匹配位置为1和3,输出1、3

代码相比模板很好改

只需要在匹配成功时输出首元素位置就好了

然后输出 next 数组……

好像该怎么骗分还是怎么骗

#include<iostream>
#include<cstring>
#include<string>
using namespace std;

const int n=1000002;
int next[n];
char s1[n],s2[n];
int len1,len2;

void getnext()
{
    int j,k;
    j=0;k=-1;next[0]=-1;
    while(j<len2)
        if(k==-1||s2[j]==s2[k])
            next[++j]=++k;
        else
            k=next[k];

}

int count()
{
    int i,j=0;
    getnext();
    for(i=0;i<len1;i++)
    {
        while(j>0&&s1[i]!=s2[j])
            j=next[j];
        if(s1[i]==s2[j])
            j++;
        if(j==len2)
        {
            cout<<i-len2+2<<endl;
            j=next[j];
        }
    }
}

int main()
{
        cin>>s1>>s2;
        len1=strlen(s1);
        len2=strlen(s2);
           count();
           for(int i=1;i<=len2;++i)
               cout<<next[i]<<' ';
    return 0;
}
原文地址:https://www.cnblogs.com/qdscwyy/p/6896081.html