算法基礎——KMP字符串匹配

原題連接ios

題目:數組

給定一個模式串S,以及一個模板串P,全部字符串中只包含大小寫英文字母以及阿拉伯數字spa

模板串P在模式串S中屢次做爲子串出現。指針

求出模板串P在模式串S中全部出現的位置的起始下標。code

輸入格式ci

第一行輸入整數N,表示字符串P的長度。字符串

第二行輸入字符串P。get

第三行輸入整數M,表示字符串S的長度。io

第四行輸入字符串S。模板

輸出格式

共一行,輸出全部出現位置的起始下標(下標從0開始計數),整數之間用空格隔開。

數據範圍
1 ≤ N ≤ 10^5
1 ≤ M ≤ 10^6

輸入樣例:

3
aba
5
ababa

輸出樣例:

0 2

解題代碼:

#include <iostream>
#include <cstdio>

using namespace std;
const int N = 100010, M = 1000010;
char p[N], s[M];
int ne[N];
int n,m;

int main(){
    cin >> n >> p + 1 >> m >> s + 1;

    //初始化next數組(尋找模板串中最長的公共先後綴)
    for(int i = 2, j = 0; i <= n; i++){
        while(j && p[i] != p[j + 1]) j = ne[j]; //前綴與後綴匹配失敗,使j回退到以前找到的公共先後綴的長度的位置,直到 p[i] 和 p[j + 1]匹配 或 j 回退到了起點(0的位置)。
        if(p[i] == p[j + 1]) j++;   //前綴的i下標元素和後綴的j+1下標元素匹配成功,並繼續匹配下一個
        ne[i] = j;  //前i個數中的最長公共先後綴的長度爲j,標記j的位置,以用來以後將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){
            printf("%d ", i - n);
            j = ne[j];  //j指針回退,繼續尋找下一個能匹配的位置
        }
    }

    return 0;
}
相關文章
相關標籤/搜索