avatar

算法-KMP字符串!!!!

KMP字符串

给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。

模板串P在模式串S中多次作为子串出现。

求出模板串P在模式串S中所有出现的位置的起始下标。

输入格式

第一行输入整数N,表示字符串P的长度。

第二行输入字符串P。

第三行输入整数M,表示字符串S的长度。

第四行输入字符串S。

输出格式

共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。

数据范围

1≤N≤1041≤N≤104
1≤M≤1051≤M≤105

输入样例:

3
aba
5
ababa

输出样例:

0 2

题解:

#include <iostream>
using namespace std;
const int N = 1e4+10;
const int M = 1e5+10;
int n,m;
int ne[N];//存储下标
char s[M],p[N];//存储字符
int main()
{
    cin >> n >> p+1 >> m >> s+1;
    //求ne过程
    for(int i=2,j=0; i<=n;i++)//如果从一开始退一步就到零不可取
    {
        while(j && p[i] != p[j+1]) j=ne[j];//匹配不成功将j移动到ne[i]
        if(p[i] == p[j+1]) j++;//匹配成功
        ne[i] = j;
    }

    //KMP 匹配过程
    for(int i=1,j=0;i<=m;i++)
    {
        while(j && s[i] != p[j+1]) j=ne[j];//j已经退无可退或者已经匹配成功
        if(s[i] == p[j+1]) j++;//将j移动到下一个位置
        if(j==n)//匹配成功
        {
            printf("%d ",i-n);
            j=ne[j];//退一步接着查找
        }
    }
    return 0;
}

stl

#include<iostream>
#include<string>
using namespace std;
string p,s;
int n,m;
int main()
{
    cin >> n >> p >> m >> s;
    for(int i=0;i<m;)
    {
        if(s.find(p,i) == string :: npos) break;//没有符合的
        cout << s.find(p,i) << " ";//输出下标
        i = s.find(p,i) + 1;//向下搜索
        if(i > m) break;//超过m的次数代表搜索完成
    }
    return 0;
}
文章作者: wangzun233
文章链接: https://wangzun233.top/2020/04/14/%E7%AE%97%E6%B3%95-KMP%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%81%EF%BC%81%EF%BC%81%EF%BC%81/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WangZun233