#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 1001000;
int n,m;
int a[M],b[10100];
int Next[10100];// next[j]=k 当b[j]失配时 应回溯到k继续匹配
//条件: 若b[j] 与 a[i] 失配时能 如果能回溯到 b[k]
// 则需要条件: "b1..bk-1"== "ai-(k-1)....ai-1"
//利用 b[j] 即部分匹配的结果 可以得到 " bj-(k-1)....bj-1" ="ai-(k-1)....ai-1"
// 所以对模式串进行 预处理 如果 "b1....bk-1" == "bj-(k-1)....bj-1"
// 即条件成立 此时 b[j]失配时 可以回溯到k
void Get_next(int m)
{
Next[1]=0;
int i=1,k=0; // k=0只能回溯到1
while(i<=m)
{
// 已知next[i]=k 递推求 next[i+1]?
// 因为"b1..bk-1"=="bi-(k-1).....bi-1"
// 若bi==bk 则"b1..bk"=="bi-(k-1)...bi"
if(k==0||b[i]==b[k])
{
Next[i+1]=k+1;
i++;
k++;
}
//
// bi!=bk 此时自己匹配自己 !!
//则 此时bk!=bi 相当于在bk处失配
// 则k不断回溯 知道 bk'=bi
// 则此时 "b1.. bk'-1 "=="bi-(k'-1).....bi-1"
else
{
k=Next[k];
}
}
}
void Kmp()
{
int i=1,j=1;
while(i<=n&&j<=m)
{
//j==0 即s[i]位置上没救了 主串前移
if(j==0 || a[i]==b[j])
{
i++;
j++;
}
else
{
j=Next[j]; // 失配时 回溯模式串j即可
}
}
if(j>m)
cout<<i-m<<endl;
else
cout<<-1<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
}
Get_next(m);
Kmp();
}
return 0;
}
HDU 1711 kmp入门
最新推荐文章于 2020-08-04 21:20:08 发布
