0
点赞
收藏
分享

微信扫一扫

Number Sequence HDU - 1711 (kmp模板)


题意:给定两个数字序列 ​​a[]​​​ 和 ​​b[]​​​,​​b[]​​​ 有可能整体作为一个连续子序列出现在了 ​​a[]​​​ 中,现在请你找出 ​​b[]​​​ 在 ​​a[]​​ 中第一次出现的位置(起始位置从 1 开始计数),如果一次都没有出现,请输出 -1。

题解:kmp模板,直接套就行了。借这个博客在小结一下kmp(好长时间没练,马上又忘了.......)

1.kmp是模式串匹配的高效算法,与直接暴力匹配算法的最大区别是建立了next数组,从而避免了重复比较。

2.next[]数组的含义:next[i]表示是在i-1位置的前缀后缀相同的最大长度,其中在求next数组时最关键的一个语句是k=next[k],这个语句的原理是利用对称性在当前匹配不成功的情况下向前寻找更小的最大“前缀后缀相同的最大长度”。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e7;
int s[maxn],p[maxn],nxt[maxn];
int n,m;
void getNext(){//获得next数组
int j=0,k=-1;
nxt[0]=-1;
while(j<m){
if(k==-1||p[k]==p[j]){
k++;
j++;
nxt[j]=k;
}
else k=nxt[k];//匹配失败寻找更小的匹配位置
}
}
int kmp(){//kmp算法,返回匹配成功的时子串在模式串中的最后一个字母的位置
int j=0,i=0;
getNext();
while(i<n){
if(j==-1||s[i]==p[j]){
i++;
j++;
}
else j=nxt[j];
if(j==m)return i;//j代表了当前子串匹配的长度,当长度完全等于子串长度时,匹配成功
}
return -1;
}
int main(){
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>s[i];
for(int j=0;j<m;j++)
cin>>p[j];
if(kmp()==-1)cout<<-1<<endl;
else cout<<kmp()-m+1<<endl;
}
}

 

举报

相关推荐

0 条评论