对于KMP算法的理解(Sunday)算法的理解

KMP算法主要是用于两段字符串进行比较的时候,进行算法的优化,当匹配到某一个值不同的时候,两个字符串移动的指针不是回朔到开始的地方,而是模式串移动到next(j)的地方,而主串(也就是要匹配的串)的动指针加1,原先暴力匹配的算法的话,时间复杂度是O(m*n),而KMP算法的复杂度为O(m+n),关键的核心就在于next(i)数组的计算

下面只能从别的代码上去抄了大笑

简单的暴力算法 

int Index_BF ( char S [ ], char T [ ], int pos )
{
/* 若串 S 中从第pos(S 的下标0≤pos<StrLength(S))个字符
起存在和串 T 相同的子串,则称匹配成功,返回第一个
这样的子串在串 S 中的下标,否则返回 -1    */
int i = pos, j = 0;
while ( S[i+j] != '/0'&& T[j] != '/0')
if ( S[i+j] == T[j] )
j ++; // 继续比较后一字符
else
{
i ++; j = 0; // 重新开始新的一轮匹配
}
if ( T[j] == '/0')
return i; // 匹配成功   返回下标
else
return -1; // 串S中(第pos个字符起)不存在和串T相同的子串
} // Index_BF

  此算法的思想是直截了当的:将主串S中某个位置i起始的子串和模式串T相比较。即从 j=0 起比较 S[i+j] 与 T[j],若相等,则在主串 S 中存在以 i 为起始位置匹配成功的可能性,继续往后比较( j逐步增1 ),直至与T串中最后一个字符相等为止,否则改从S串的下一个字符起重新开始进行下一轮的"匹配",即将串T向后滑动一位,即 i 增1,而 j 退回至0,重新开始新一轮的匹配。

而KMP算法就是在模式串的匹配上,进行了优化,模式串移动到next(i)的地方,进行比较

下面主要来讲讲next(i)的计算规则

next[0] = -1 ,任何串的第一个字符的模式值都为 -1

next[j] = -1,模式串T中下标为j的字符,如果与首字符相同,且j的前面1-k个字符与开头的1-k个字符不等(或者相等但T[K] == T[J] )(1<=k<j)

 next(j) = k 模式串T中下标j的字符,如果j的前面k个字符与开头的k个字符相同,且T[j]!= T[k],

next[j] = 0, 除上述三种情况外

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
//定义主串s和模式串t
string s, t;
//定义next数组 
int next1[100];
//next函数的获得方法
void getNext() {
	int j, k;
	j = 0;
	k = -1;
	//next[0]为-1这是死规定
	next1[0] = -1;
	while (j < t.length()) {
		if (k == -1 || t[j] == t[k])
			next1[++j] = ++k;
		else
			k = next1[k];
	}
	}
//返回模式串在主串s中首次出现的位置
int Kmp_Index() {
	int i = 0, j = 0;
	getNext();
	while (i < s.length() && j < t.length()) {
		if (j == -1 || s[i] == t[j])
		{
			i++;
			j++;
		}
		else
			j = next1[j];
	}
		if (j == t.length())
			return i - t.length();
		else
			return -1;
	}
//返回模式串t在主串s中出现的次数
int kmp_Count() {
	int ans = 0;
	int i, j = 0;
	if(s.length() == 1 && t.length() == 1)
	{
		if (s[0] == t[0])
			return 1;
		else
			return 0;
	}
	getNext();
	for (i = 0; i < s.length(); i++) {
		//cout << i << " " << j << endl;
		while (j>0 && s[i] != t[j])
			j = next1[j];
		if (j == t.length()) {
			ans++;
			j = next1[j];
		}
	}
	return ans;
}
int main()
{
	int tt;
	cin >> tt;
	while (tt--)
	{
		cin >> s >> t;
		cout << Kmp_Index() << endl;
		printf("%d\n", kmp_Count());
		// for(int i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);  
	}
	return 0;
}

具体可看这两个博客

http://blog.csdn.net/java2king/article/details/5273551

http://blog.csdn.net/zhoujiachengdhy/article/details/24412671

各种字符串匹配的算法 可以看这个

http://dsqiu.iteye.com/blog/1700312

Sunday算法的描述可以看这个

http://baike.baidu.com/link?url=IcfTrZap5zMaPAeyQCaaI_1CskUSI-STaL91fWlMrTy0L50Kuwu3j_z-THeIh4F-MCi6a2de7xaqL3xuiOUPh_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值