831. KMP字符串

题目描述
给定一个模式串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;
}
发布了80 篇原创文章 · 获赞 168 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/wmy0217_/article/details/104622429