1. 程式人生 > >CH1809匹配統計【KMP】

CH1809匹配統計【KMP】

位置 ostream 長度 void ons 同學 code abcd names

1809 匹配統計 0x18「基本數據結構」練習

描述

阿軒在紙上寫了兩個字符串,分別記為A和B。利用在數據結構與算法課上學到的知識,他很容易地求出了“字符串A從任意位置開始的後綴子串”與“字符串B”匹配的長度。

不過阿軒是一個勤學好問的同學,他向你提出了Q個問題:在每個問題中,他給定你一個整數x,請你告訴他有多少個位置,滿足“字符串A從該位置開始的後綴子串”與B匹配的長度恰好為x。

例如:A=aabcde,B=ab,則A有aabcde、abcde、bcde、cde、de、e這6個後綴子串,它們與B=ab的匹配長度分別是1、2、0、0、0、0。因此A有4個位置與B的匹配長度恰好為0,有1個位置的匹配長度恰好為1,有1個位置的匹配長度恰好為2。

輸入格式

第一行三個整數N,M,Q,表示A串長度、B串長度、問題個數。

第二行是字符串A,第三行是字符串B。

接下來Q行每行1個整數x,表示一個問題。

1<=N,M,Q,x<=200000.

輸出格式

共Q行,依次表示每個問題的答案。

樣例輸入

6 2 5
aabcde
ab
0
1
2
3
4

樣例輸出

4
1
1
0
0

來源

北京大學2015年數據結構與算法A期末考試

題意:一個字符串a, 一個字符串b。對於每一個詢問x,問a的後綴中與b匹配長度恰好為x的數量是多少。

思路:開始的時候用了Hash,枚舉開始節點,顯然會T。還沒想到優化。

後來看了題解寫了KMP。用KMP先求出以a[i]為開頭的後綴與b匹配的最長長度。

cnt[x]存儲的是匹配長度>=x的位置的個數

【還有點不理解,晚點等家庭教師拯救.....】

 1 #include <iostream>
 2 #include <set>
 3 #include <cmath>
 4 #include <stdio.h>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <queue>
 9 #include <map>
10 using
namespace std; 11 typedef long long LL; 12 #define inf 0x7f7f7f7f 13 #define pr pair<int, int> 14 #define mp make_pair 15 16 int n, m, q; 17 const int maxn = 2e5 + 10; 18 char a[maxn], b[maxn]; 19 unsigned long long Ha[maxn], Hb[maxn], p[maxn]; 20 21 int nxt[maxn], f[maxn], cnt[maxn]; 22 void getnxt() 23 { 24 nxt[1] = 0; 25 for(int i = 2, j = 0; i <= m; i++){ 26 while(j > 0 && b[i] != b[j + 1])j = nxt[j]; 27 if(b[i] == b[j + 1])j++; 28 nxt[i] = j; 29 } 30 } 31 32 int main() 33 { 34 scanf("%d%d%d", &n, &m, &q); 35 scanf("%s", a + 1); 36 scanf("%s", b + 1); 37 getnxt(); 38 for(int i = 1, j = 0; i <= n; i++){ 39 while(j > 0 && (j == m || a[i] != b[j + 1]))j = nxt[j]; 40 if(a[i] == b[j + 1])j++; 41 f[i] = j; 42 } 43 for(int i = 1; i <= n; i++){ 44 cnt[f[i]]++; 45 } 46 for(int i = n; i >= 1; i--){ 47 cnt[nxt[i]] += cnt[i]; 48 } 49 /*p[0] = 1; 50 for(int i = 1; i <= n; i++){ 51 Ha[i] = Ha[i - 1] * 131 + a[i] - ‘a‘ + 1; 52 Hb[i] = Hb[i - 1] * 131 + b[i] - ‘a‘ + 1; 53 p[i] = p[i - 1] * 131; 54 }*/ 55 56 while(q--){ 57 int x; 58 scanf("%d", &x); 59 /*if(x > min(n, m)){ 60 printf("0\n"); 61 continue; 62 } 63 int hashb = Hb[x] - Hb[0] * p[x]; 64 int hb = Hb[x + 1] - Hb[0] * p[x + 1]; 65 int cnt = 0; 66 for(int i = 1; i <= n; i++){ 67 int hasha = Ha[i + x - 1] - Ha[i - 1] * p[x]; 68 int ha = Ha[i + x] - Ha[i - 1] * p[x + 1]; 69 70 if(hasha == hashb && ha != hb){ 71 cnt++; 72 } 73 }*/ 74 75 printf("%d\n", cnt[x] - cnt[x + 1]); 76 } 77 78 return 0; 79 }

CH1809匹配統計【KMP】