原題連接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; }