[AcWing 831] KMP字符串

image
image


点击查看代码
#include<iostream>

using namespace std;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
int ne[N];
int main()
{
    int n, m;
    char p[N], s[M];
    cin >> n >> p + 1 >> m >> s + 1;
    for (int i = 2, j = 0; i <= n; i ++) {
        while (j && p[i] != p[j + 1])   j = ne[j];
        if (p[i] == p[j + 1])   j ++;
        ne[i] = j;
    }
    for (int i = 1, j = 0; i <= m; i ++) {
        while (j && s[i] != p[j + 1])   j = ne[j];
        if (s[i] == p[j + 1])   j ++;
        if (j == n)  {
            cout << i - j << ' ';
            j = ne[j];
        }
    }
    return 0;
}

  1. ne 数组用来记录下一次 j 应当从哪个位置开始继续匹配;
  2. p 和 s 都从数组下标为 1 开始存放;
  3. 求 ne 数组的过程:当 j 不为 0 并且 p[ i ] != p[ j + 1 ] 说明 j 应当往回退,直到 j 到达 0 或者满足前缀等于后缀的位置,如果 p[ i ] == p[ j + 1 ],则 j ++,表示下一次从后面这个位置开始匹配,最后 ne[ i ] = j 用来 ne 数组的值;
  4. 匹配的操作和求 ne 的操作类似,当满足 j == n 时,说明匹配成功,输出位置,并让 j = ne[ j ],注意输出的时候是 i - j + 1 - 1(i - j + 1 表示 s 数组匹配成功的起始下标,- 1 是因为定义的 s 数组是从下标为 1 开始的,而题目要求的是要从 0 开始的下标);
posted @ 2022-05-02 16:35  wKingYu  阅读(30)  评论(0)    收藏  举报