HDU-1711-Number Sequence(模式串匹配)
Posted angel-demon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU-1711-Number Sequence(模式串匹配)相关的知识,希望对你有一定的参考价值。
- Rabin-Karp
Accepted 1711 904MS 5272K 1310 B G++ #include "bits/stdc++.h" using namespace std; typedef long long LL; const int MAXN = 1e6 + 5; const int SEED = 1e9 + 7; int arr[MAXN]; int main() { int t, n, m, k; scanf("%d", &t); while (t--) { LL p = 0, s = 0, head = 1; bool flag = false; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &arr[i]); } // 获取模式串(M数组)的哈希值 for (int i = 1; i <= m; i++) { scanf("%d", &k); head *= SEED; p = p * SEED + k; } // 获取arr[0]所表示的长度为m的串的哈希值 for (int i = 1; i < m; i++) { /* 比较标准的写法是s = (s * SEED + arr[i]) % MOD;(MOD是一个和SEED互质的数) 这里利用LL的溢出来省略MOD,可以将MOD看成2的64次方 */ s = s * SEED + arr[i]; } for (int i = 1; i <= n - m + 1; i++) { // 用arr[i - 1]所表示的长度为m的串的哈希值得到arr[i]所表示的长度为m的串的哈希值 s = s * SEED - head * arr[i - 1] + arr[i + m - 1]; if (s == p) { flag = true; printf("%d ", i); break; } } if (!flag) { puts("-1"); } } return 0; }
Rabin-Karp获取哈希值的形式有点像进制转换,由于计算机内二进制加减是不管符号的所以p和s变成负数也无所谓,用unsigned long long和long long是一样的。但是Rabin-Karp不保证匹配结果绝对正确,因为不同的串哈希值可能一样(long long的范围只有2的64次方,但是本题数组值的范围是[-1000000, 1000000],只要三四位产生的串的数量long long就不够放了)所以如果竞赛中用此法错了,可以尝试改SEED。还不行那就只能换方法了。
以上是关于HDU-1711-Number Sequence(模式串匹配)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 1711 Number Sequence(KMP模板)