Bootstrap

KMP算法实现(C++)


一、问题描述

实现KMP算法

二、实现思路

在KMP算法中,首先分析模式串t从中提取出加速匹配的有用信息next数组,紧接着利用计算好的模式串的next数组进行模式匹配。其中,next数组有效地消除了主串指针的回溯,提高算法效率

  • 第一部分,对模式串预处理,生成next数组。next数组的求解过程如下:

(1)置next[0]=-1,next[1]=0。
(2)如果next[j]=k,表示有”t0t0…tk-1”=”tj-k-tj-k+1…tj-I”:
①若tk=tj,既有”t0t0…tk-1tk”=”tj-k-tj-k+1…tj-I tj”,显然有next[j+1]=k+1。
②若tk≠tj,说明tj之前不存在长度为next[j]+1的子串和开头字符起的子串相同,设k’=next[k],则下一步应该将tj与tk’比较:若tj=tk’,则说明tj之前存在长度为next[k’]+1的子串和开头字符起的子串相同;否则依次类推找更短的子串,直到不存在可匹配的子串,置next[j+1]=0。所以,当tk≠tj时,置k=next[k]。

  • 第二部分,利用计算好的模式串的next数组进行模式匹配。过程如下:

假设指针i和j分别指向目标串s和模式串t。首先将i和j分别置0,再分别扫描目标串s和模式串t,如果j=-1或者i和j指向的字符相同,i和j分别自增1;否则,i不变,j回退到j=next[j]即模式串右滑.当跳出循环后,通过j的值进行判断。如果j超界,说明模式匹配成功,返回i-t的长度;否则,说明模式匹配失败,返回值-1.

三、程序代码

#include<iostream>
using namespace std;
#define MaxSize 50
typedef struct                                //类型声明
{
	char data[MaxSize];
	int length;
}SqString;
void StrAssign(SqString & s, char cstr[])     //将字符串常量cstr赋给串
{
	int i;
	for (i = 0; cstr[i] != '\0'; i++)
		s.data[i] = cstr[i];
	s.length = i;
}
void DestroyStr(SqString &s) {}                  //销毁串         
void GetNext(SqString t, int next[])             //由模式串t求出next数组
{
	int j, k;
	j = 0; k = -1;
	next[0] = -1;
	while (j < t.length - 1)
	{
		if (k == -1 || t.data[j] == t.data[k])
		{
			next[j++] = k++;
		}
		else
			k = next[k];
	}
}
int KMPIndex(SqString s, SqString t)               //KMP算法 
{
	int next[MaxSize], i = 0, j = 0;
	GetNext(t, next);
	while (i < s.length&&j < t.length)
	{
		if (j == -1 || s.data[i] == t.data[j])
		{
			i++; j++;
		}
		else j = next[j];
	}
	if (j >= t.length)
		return(i - t.length);
	else
		return -1;
}
int main()
{
	char a[MaxSize], b[MaxSize];
	SqString astr, bstr;
	cout << "请输入目标串:";
	cin >> a;
	cout << "请输入模式串:";
	cin >> b;
	StrAssign(astr, a);
	StrAssign(bstr, b);
	cout <<"模式串位置为:"<< KMPIndex(astr, bstr) << endl;
}

四、运行结果

在这里插入图片描述

;