CH1809匹配统计KMP

Posted wyboooo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH1809匹配统计KMP相关的知识,希望对你有一定的参考价值。

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
");
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
", cnt[x] - cnt[x + 1]);
76     }
77 
78     return 0;
79 }

 

以上是关于CH1809匹配统计KMP的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(C语言版)严蔚敏(字符串的模式匹配算法--KMP算法)

数据结构(C语言版)严蔚敏(字符串的模式匹配算法--KMP算法)

字符串截取模板 && POJ 34503080 ( 暴力枚举子串 && KMP匹配 )

kmp算法next(j)怎么算出来的?

BF算法中 s.ch[1] i=i-j+2怎么理解?

kmp算法的个人理解