KMP算法/POJ3461(求匹配字符子串的个数)

1.Next数组

next[j]={

j=1时,0

j!=1时,最大子串长度+1,即P1P2….Pk-1==Pj-k+1….Pj-1,1<k<j,(看来j=2时是没有最大子串的,因此next[2]一定为1)

其它情况,1

}

next[j]=0说明模式串与匹配串都要后移一位

next[j]!=0说明匹配串的当前字符与next[j]匹配

next数组的下标从1开始,因此我们在模式串(T)的前面添加一个字符‘#’,初始化next[1]=0

求每个next[j](j>1)时实际上利用到上next[j-1]的值

如求next[5]时,则查看next[4]的值,如果T[4]=T[next[4]],则next[5]=next[4]+1

如果T[4]!=T[next[4]],T[4]再与next[T[next[4]]]比,如果相等,则next[5]=next[T[next[4]]]+1,如此继续,如果它的next值为0,则跳到其它情况

因此,标准算法如下:

void get_next()
{
	unsigned int length = strlen(t);
	next[0]=0;
	next[1]=0;
	unsigned int i=1,j=next[1];
	while(i<length-1){
		if(j==0){
			i++;
			j=1;
			next[i]=1;
			continue;
		}
		if(t[i]==t[j]){
				i++;
				j++;
				next[i]=j;
		}else 
			j = next[j];
	}
	
}

这段代码优化一下:

scanf("%s",t+1);

t[0]=’#’;

void get_next()
{
	unsigned int length = strlen(t);
	//next[0]=0;
	next[1]=0;
	unsigned int i=1,j=next[1];
	while(i<length-1){
		
		if(j==0||t[i]==t[j]){
				i++;
				j++;
				next[i]=j;
		}else 
			j = next[j];
	}
	
}

对于POJ3461,next数组要多求一位

要求:求出上串在下串中出现的次数

Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output
1
3
0

#include <iostream>
using namespace std;
#define MAX 1000003
unsigned int next[MAX];
char s[MAX];
char t[MAX];
void get_next()
{
	unsigned int length = strlen(t);
	next[0]=0;
	next[1]=0;
	unsigned int i=1,j=next[1];
	while(i<length){
		
		if(j==0||t[i]==t[j]){
				i++;
				j++;
				next[i]=j;
		}else 
			j = next[j];
	}
	
}
unsigned int kmp(){
	unsigned int length = strlen(s)-1;
	unsigned int matLen = strlen(t)-1;
	if(length<matLen)return 0;
	unsigned int i=1,j=1,count = 0;
	while(i<=length){
		
		if(j==0||s[i]==t[j]){
			i++;
			j++;
			
		}
		else j = next[j];
		if(j==matLen+1){
			count++;
			j = next[j]; 
			}

	}
	return count;
}

int main()
{
	freopen("i://in.txt","r",stdin);
	int count;
	scanf("%d",&count);
	t[0]='#';
	s[0]='#';
	for(int i=0;i<count;i++){
	scanf("%s",t+1);
	scanf("%s",s+1);
	get_next();
	printf("%d\n",kmp());
	
	}
	return 0;
}

转载于:https://www.cnblogs.com/yangyh/archive/2011/05/29/2061913.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值