KMP字符串匹配 模板 洛谷 P3375

北战南征 提交于 2019-12-03 02:05:28

KMP字符串匹配 模板 洛谷 P3375

题意

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

为了减少骗分的情况,接下来还要输出子串的前缀数组next。(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)

样例:

输入
ABABABC
ABA
输出
1
3
0 0 1 

解题思路

当然是使用KMP啦,只不过这个要求比较高一些。

注意这里要输出的next数组内容是不能进行优化的那种,否者就会WA,带有优化的那种看第二个代码。

详情见代码。这个也可以算作一个模板了。

代码实现

void getnext()               //做的第一步是获得next【】的值
{
    int i=0,k=-1;
    next[0]=-1;
    while(i<lenb)
    {
        if(k==-1)//这里和平常的有些不同,这里进行了一些优化,将两个条件分开了。
        {
            next[++i]=++k;
            continue;
        }
        if (b[i]==b[k]) 
        {
            if(b[i+1]==b[k+1]) //这里进行了优化,一般介绍KMP的文章中都有会这个。
                next[++i]=next[++k]; 
            else 
                next[++i]=++k;
        }
        else k=next[k];
    }
}
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e6+7;
char a[maxn],b[maxn];
int next[maxn];
int lena, lenb;
void getnext()               //做的第一步是获得next【】的值
{
    int i=0,k=-1;
    next[0]=-1;
    while(i<lenb)
    {
        if (k==-1 || b[i]==b[k])
            next[++i]=++k;
        else k=next[k];
    }
}
void KMP()
{
    getnext();
    int i=0,j=0,cnt=0;
    while (i<lena)
    {
        if (j==-1||a[i]==b[j])
        {
            i++;j++;
        }
        else j=next[j];
        if (j==lenb)
        {
            printf("%d\n", i-j+1);
            j=next[j];
        }   
    }   
}
int main()
{
    while(scanf("%s",a)!=EOF)
    {
        scanf("%s",b);
        lena=strlen(a);
        lenb=strlen(b);
        KMP();
        for(int i=1; i<=lenb; i++)
        {
            printf("%d ", next[i]);
        }
        printf("\n");
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!