KMP及其扩展算法——源码、注释

关于KMP及其扩展的讲解有很多,可以自己百度下。

此文为个人的源码及整理的注释。

本人第一次写博文的菜鸟,将就着看吧。。。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
char S[100],T[100];//S->母串,T->子串 
int perfix[100],n=0,m=0,next[100],extend[100];
//perfix[i]->T[1...perfix[i]-1]==T[i-perfix[i]+1...i-1]:T[1...perfix[i]]是 T[i-perfix[i]+1...i-1]的前缀,且perfix最大 
//next[i]->T[1...next[i]]=T[i...m]:使T[1...next]==T[i...i+next-1]的最大next 
//extend[i]->T[1...extend[i]]=S[i...i+extend[i]-1]:使T[1...extend]==S[i...i+extend-1]的最大extend 

void _orgin()//base 
{
	int k=0;//T中当前位置的指针 
	perfix[1]=0;//对于首次出现的字符,perfix为0 
	for(int i=2;i<=m;i++)
	{
		while(k>0 && T[k+1]!=T[i])k=perfix[k]; //若失配,则将指针调至perfix进行匹配 
		if(T[k+1]==T[i])k++;//若匹配成功,指针后移 
		perfix[i]=k;//若匹配失败,则k必定为0 
	}
}

void _KMP()//base
{
	int k=0;//同上 
	for(int i=1;i<=n;i++)
	{
		while(k>0 && T[k+1]!=S[i])k=perfix[k];//同上 
		if(T[k+1]==S[i])k++;//同上 
		if(k==m)printf("%d\n",i-m+1);//若k==m,即找到了T在S中的位置 
	}
}

void KMP_extend()//extend
{
	next[1]=m;
	next[2]=m-1;
	for(int i=1;i<=m;i++)//预处理出next[2]的值 
	{
		if(T[i+1]!=T[i])
		{
			next[2]=i-1;
			break;
		}
	}
	int p,k=2,j,L;//p->当前最远匹配 ,使匹配最远的k 
	for(int i=3;i<=m;i++)//此为T与自己的extend_kmp 
	{
		p=k+next[k]-1;L=next[i-k+1];
	//由next定义(见变量申明下方的注释)->T[k...p]==T[1...p-k+1] ->T[i...p]==T[i-k+1...p-k+1] 
		if(i+L<=p)//讨论i+L与p的关系 
		{
			next[i]=L;
		}
		else 
		{
			j=p-i+1;//已知的长度 
			j=max(j,0);
			while(i+j<=m && T[i+j]==T[j+1])j++;//未知串检测匹配 
			next[i]=j;k=i;
		}
	}
	k=1;
	extend[1]=m;
	for(int i=1;i<=m;i++)//此为S与T的extend_kmp 
	{
		if(S[i]!=T[i])
		{
			extend[1]=i-1;
			break;
		}
	}
	for(int i=2;i<=n;i++)
	{
		p=k+extend[k]-1;L=next[i-k+1];
		if(i+L<=p)
		{
			extend[i]=L;
		}
		else
		{
			j=p-i+1;
			j=max(j,0);
			while(i+j<=n && j<=m && S[i+j]==T[j+1])j++;
			extend[i]=j;k=i;
		}
	}
	for(int i=1;i<=m;i++)printf("next[%d]:%d\n",i,next[i]);
	for(int i=1;i<=n;i++)printf("extend[%d]:%d\n",i,extend[i]);
}

int main()
{
	freopen("Kmp.in","r",stdin);
	freopen("Kmp.out","w",stdout);
	char a=getchar();
	while(a!='\n')
	{
		S[++n]=a;
		a=getchar();
	}
	a=getchar();
	while(a!='\n')
	{
		T[++m]=a;
		a=getchar();
	}
	_orgin();
	_KMP();
	KMP_extend();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值