题目描述
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。
模板串P在模式串S中多次作为子串出现。
求出模板串P在模式串S中所有出现的位置的起始下标。
输入格式
第一行输入整数N,表示字符串P的长度。
第二行输入字符串P。
第三行输入整数M,表示字符串S的长度。
第四行输入字符串M。
输出格式
共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。
数据范围
1≤N≤104
1≤M≤105
输入样例:
3
aba
5
ababa
输出样例:
0 2
①主串和模式串均从下标为1开始存入,所以是cin>>n>>p+1>>m>>s+1
②首先,我们是让 i 从1开始,j 从0开始,每次比较 s[i] 与 p[j+1]
③kmp匹配过程是模式串与主串匹配的过程。就是比较 s[i] 和 p[j+1] 是否相等,不相等则让j=ne[j],此时还不相等的话,j=ne[ne[j]],再不相等的话,继续这样调用下去(递归),一直让j往左边退,直到 j 退到0或者满足s[i]=p[j+1],j=0则表示从主串的下一个字符开始匹配,s[i]=p[j+1]后要使j++(使模式串的下一个字符进行匹配),当 j=n时,则匹配成功,匹配成功后还要令 j=ne[j],让 j 往左退来和下一个s[i]进行匹配
④求next数组的过程就是模式串自己与自己匹配的过程,这个过程和kmp匹配过程一样
⑤时间复杂度O(n)
#include<iostream>
using namespace std;
const int N=1e4+10,M=1e5+10;
int n,m;
char p[N],s[M];
int ne[N]; //ne[]为next数组
int main()
{
cin>>n>>p+1>>m>>s+1; //从1开始存字符串
// 求next
for(int i=2,j=0;i<=n;i++)
{
while(j && p[i]!=p[j+1]) j=ne[j];
if(p[i]==p[j+1]) j++;
ne[i]=j;
}
// KMP匹配
for(int i=1,j=0;i<=m;i++)
{
while(j && s[i]!=p[j+1]) j=ne[j];
if(s[i]==p[j+1]) j++;
if(j==n)
{
cout<<i-n<<" ";
j=ne[j];
}
}
return 0;
}