字符串KMP模式匹配算法

#include<iostream>
#include<stdio.h>
#include<string>
#include"structfun.h"

using std::string;
using std::printf;
using std::scanf;
using std::endl;
using std::to_string;


int main()
{
//KMP模式匹配算法

//1、定义两个字符数组S1(主串),S2(查找子串)
//2、求出S2的next数值
//3、根据next数值匹配S1主串
#define MAXSIZE 100
char S1[MAXSIZE];
char S2[MAXSIZE];
int next[MAXSIZE];

printf("输入主串S1:");
cin>>S1;

printf("输入子串S2:");
cin>>S2;

//求S2的next值
	//例:S2=abdabg
	//	next[0]=0; next[1]=1 a next[2] =1 a ab; next[3]=1 a ab abd
	//	next[4]=2 a=a ab abd abda; 一个重复
	//	next[5]=3 a=a ab=ab abd abda abdab两个重复
	//	既next[0]=0 next[i]=1+(i的字符前缀和后缀相等字符串的长度) next[5]就是“ab”的长度加1既是3
//采用两个循环计算next值
//next[0]=0;
//next[1]=1;
//从第三个值开始计算,前两个位0、1
//int i=2,n=1;
//while(S2[i]!=0)
//{
//	//提取前端跟后端的字符串相比a ab abd abda abdab
//	int bf,af;
//	bf=1;
//	af=i;
//	string bs,as;
//	for(int j=1;j<af;j++)
//	{
//		bs=bs+S2[j-1];
//		as=S2[af-j]+as;
//		if(bs==as)
//		{
//			n=bs.length()+1;
//		}
//	}
//	next[i]=n;
//	i++;
//}
//****还是需要两个循环**还是有回溯 不好


		//改进 分析ababaaabad
		//                             0	next[0]
		//a                            1	next[1]
		//a b        s[0]!=s[1]        1	next[2]
		//aba        s[0]=s[2]         2	next[3]
		//abab       s[1]=s[3]         3	next[4]
		//ababa      s[2]=s[4]         4	next[5]
		//ababaa     s[3]!=s[5]        2	next[6]回溯到上次不相等
		//ababaaa    s[1]!=s[6]        2	next[7]回溯到上次不想等
		//ababaaab   s[1]=s[7]         3	next[8]
		//ababaaaba  s[2]=s[8]         4	next[9]

next[0]=0;
next[1]=1;
int i=1,k=1,nb=0;
while(S2[i+1]!=0)
{
	if(S2[nb]!=S2[i])//不相等回溯
	{
		if(nb==0)
			k=1;
		else
		k=next[nb];
	}
	else
	{
		k++;
		nb++;
	}
	//KMP改进,加判断前缀的前一个和后缀的后一个是否相等,相等则直接next[i+1]=前缀的前一个
	if(S2[i+1]==S2[nb])
		next[i+1]=next[nb];
	else
		next[i+1]=k;
	i++;
}





//与主字符串进行比较。一个循环遍历主字符串
int f1=0,f2=0;
string str;
str=S2;
while(S1[f1]!=0)
{
	if(S1[f1]==S2[f2])
	{
		f1++;
		f2++;
	}else 
	{
		if(next[f2]==0)
			f1++;
		else
		f2=next[f2]-1;
	}
		 if (S2[f2]==0)
	{
		printf("找到了,在%d位置\n",f1-str.length()+1);	
		//f1++;
		f2=0;
	}
	
}

	system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值