最初级的kmp
next数组有模式串计算得来。
相对于朴素匹配的区别在于,主串的 i 不再后退,而只是扫描一遍过去。当发现不匹配的时候,根据next数组的找到模式串的对应位置进行比较。
next的值由 最前真前缀和真后缀的最大长度决定。具体参考数据结构课本。
#include <iostream>
#include <cstring>
using namespace std;
void get_nextval(int* T, int nextval[])
{
int i = 1, j = 0;
nextval[1] = 0;
while(i < T[0])
if(j == 0 || T[i] == T[j]) {
++i;
++j;
if(T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
} else
j = nextval[j];
}
int Index_KMP(int* S, int* T, int pos, int next[])
{
int i = pos, j = 1;
while(i <= S[0] && j <= T[0])
if(j == 0 || S[i] == T[j]) {
++i;
++j;
} else
j = next[j];
if(j > T[0])
return i - T[0];
else
return -1;
}
int main()
{
int t;
cin >> t;
while(t--) {
int n, m, i;
cin >> n >> m;
int *s1 = new int[n + 1];
s1[0] = n;
int *s2 = new int[m + 1];
s2[0] = m;
for(i = 1; i <= n; i++)
scanf("%d", &s1[i]);
for(i = 1; i <= m; i++)
scanf("%d", &s2[i]);
int *next = new int[m+1];
get_nextval(s2, next);
printf("%d\n", Index_KMP(s1, s2, 1, next));
delete[] s1;
delete[] s2;
delete[] next;
}
return 0;
}