kmp算法模板和基础应用

模板题:https://www.acwing.com/problem/content/833/
题意:给两个字符串长度及序列,求第一个串在第二个串中出现的位置

 3
aba
 5
ababa

求next数组:

for(int i=2,j=0;i<=m;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<=n;i++){
	while(j&&s[i]!=p[j+1])j=ne[j];
	if(s[i]==p[j+1])j++;
	if(j==m) j=ne[j];  //避免下次的p[j+1]越界
}

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+5;
char s[N], p[N];
int ne[N];

int main(){
	int m,n;
	cin>>m>>p+1>>n>>s+1;
	for(int i=2,j=0;i<=m;i++){
		while(j&&p[i]!=p[j+1]) j=ne[j];
		if(p[i]==p[j+1]) j++;
		ne[i]=j;
 	}
 	
 	for(int i=1,j=0;i<=n;i++){
 		while(j&&s[i]!=p[j+1]) j=ne[j];
 		if(s[i]==p[j+1]) j++;
 		if(j==m){
 			printf("%d ",i-m);
 			j=ne[j];   //不加的话,下次循环p[j+1]越界 
		}
	}
	return 0;
	 
} 

基础用法:
利用前缀和求字符串最小循环节的长度、循环节的个数
最小循环节长度:len-ne[len]
循环节个数: len/(len-ne[len])

Cyclic Nacklace:http://acm.hdu.edu.cn/showproblem.php?pid=3746
题意:使一个字符串成为一个循环字符串的,最少要添加多少个字符

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e6+5;
char s[N];
int ne[N];
int main(){
	int T; cin>>T;
	while(T--){
		scanf("%s",s+1);
		int len=strlen(s+1);
		for(int i=2,j=0;i<=len;i++){
			while(j&&s[i]!=s[j+1]) j=ne[j];
			if(s[i]==s[j+1]) j++;
			ne[i]=j;
		}
		
		int add_len=len-ne[len]-len%(len-ne[len]);
		if(len%(len-ne[len])==0) add_len=0;  //本身就循环 
		if(!ne[len])add_len=len;  //整个是一个循环节 
		printf("%d\n",add_len);				
	}
}

上一篇:哈斯(Hasse)图


下一篇:成语接龙(深搜模板)