You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
/*
|
|
|
|
|
Rabin_Karp:虽说用KMP更好,但是RK算法好理解。简单说一下RK算法的原理:首先把模式串的哈希值算出来,
|
|
|
|
|
在文本串里不断更新模式串的长度的哈希值,若相等,则找到了,否则整个模式串的长度的哈希值向右移动一位
|
|
|
|
|
*/
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
typedef unsigned long long ULL;
|
|
|
|
|
const int N = 1e4 + 10;
|
|
|
|
|
const int M = 1e6 + 10;
|
|
|
|
|
const ULL KEY = 100000007;
|
|
|
|
|
int s[M], p[N];
|
|
|
|
|
int n, m;
|
|
|
|
|
|
|
|
|
|
int match() {
|
|
|
|
|
ULL h = 1;
|
|
|
|
|
for (int i = 0; i < n; i++) h *= KEY;
|
|
|
|
|
|
|
|
|
|
//对齐0~n-1
|
|
|
|
|
ULL ah = 0, bh = 0;
|
|
|
|
|
for (int i = 0; i < n; i++) ah = ah * KEY + s[i]; //模拟成KEY进制,然后利用ULL溢出的形式,相当于对2^64取模
|
|
|
|
|
for (int i = 0; i < n; i++) bh = bh * KEY + p[i];
|
|
|
|
|
|
|
|
|
|
//开始尝试匹配
|
|
|
|
|
for (int i = 0; i <= m - n; i++) {
|
|
|
|
|
if (ah == bh) return i + 1; //如果HASH值一致,则返回匹配位置,因本题要求数组下村从1开始,所以+1后返回
|
|
|
|
|
if (i < m - n) ah = ah * KEY + s[i + n] - s[i] * h; //怕越界,因为数据弱,不写if也能AC,但如果模式串最后一位是0,就狒狒了,原因看EXCEL
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
int T;
|
|
|
|
|
scanf("%d", &T);
|
|
|
|
|
while (T--) {
|
|
|
|
|
scanf("%d%d", &m, &n);
|
|
|
|
|
for (int i = 0; i < m; i++) scanf("%d", &s[i]); //源串
|
|
|
|
|
for (int i = 0; i < n; i++) scanf("%d", &p[i]); //模式串
|
|
|
|
|
printf("%d\n", match());
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|