串的模式匹配

目标串:s(从该字符串中查找)
模式串:t(需要从s中匹配的字符串)

1.BF算法:
采用穷举法,分别从s串的第一个字符开始与t串进行匹配,若相同则分别加1,不相同则s串进一格,t串回到开头再次与s串进行比较。

int BF(string t, string s)
{
	int i = 0, j = 0;		//i,j分别作为t,s上的游标
	while (i < t.length() && j < s.length())
	{
		if (t[i] == s[j])
		{
			i++;
			j++;
		}
		else
		{
			j = j - i + 1;	//j回到s串中下一个字符
			i = 0;
		}
	}
	if (i == t.length())
	{
		return j - i;
	}
	else
	{
		return -1;
	}
}

BF算法比较简单易懂,但是效率不高。假设s串有m个字符,t串有n个字符
最坏时间复杂度(mn)
平均时间复杂度(m
n)

2.KMP算法
考虑到BF算法的缺点KMP算法充分的利用了之前匹配完成的信息,从而加了匹配速度。
原理:
引入子串的概念对模式串t进行分析。若该字串t具有某种规律,即可利用之前已经和s串匹配好的信息,从而省去s串回溯的过程。若t串的第t[j]具有性质t[1]t[2]=t[j-2]t[j-1]那么根据之前已经匹配好的信息可知t[1]t[2]处的字符串与s串中与t[j-2]t[j-1]相匹配的字符完全相同,那么我们就可以省去s的回溯并直接将t[3]与s上游标所指的字符进行比较。
在这里插入图片描述
这样可以将已经适配好的字符串看做是t串的一部分,此时根据next数组的算法可知当且仅当t头子串和s尾子串匹配时这一种情况符合,否则t串不可能与s串匹配。

int BF(string t, string s)
{
	int i = 0, j = 0;		//i,j分别作为t,s上的游标
	while (i < t.length() && j < s.length())
	{
		if (t[i] == s[j])
		{
			i++;
			j++;
		}
		else
		{
			j = j - i + 1;
			i = 0;
		}
	}
	if (i == t.length())
	{
		return j - i;
	}
	else
	{
		return -1;
	}
}

int FindNext(string t,int* next)	//寻找next数组方法1
	int index = 0;
	int i = -1;
	int j = 0;
	while (index < t.length())
	{
		if (index == 0)
		{
			next[index] = 0;
			index++;
		}
		if  (i==-1 ||t[i] == t[j])
		{
			i++;
			j++;
			next[index] = i;
			index++;
		}
		else
		{
			i = 0;
			while (t[i] == t[j])
			{
				j--;
			}
			while (j < index)
			{
				if (t[i] == t[j])
				{
					i++;
					j++;
				}
				else
				{
					i = 0;
					j++;
				}
			}
			next[index] = i;
			index++;
		}
	}
	return 0;
}

int KMPNext(string t,int* next)		//KMP算法中寻找next数组的方法
{
	int i = 0;		//t串索引,不发生回退
	int j = -1;		//记录相同元素个数
	next[0] = -1;
	while (i < t.length())
	{
		if (j == -1 || t[i] == t[j])
		{
			i++;
			j++;
			next[i] = j;
		}
		else
		{
			j = next[j];		//利用之前得到的加速匹配信息来减少回退
		}
	}
	return 0;
}

int KMP(string t, string s)
{
	int i=0;		//s串游标
	int k = -1;		//匹配成功字符个数
	int next[20];
	KMPNext(t, next);
	while (k<(int)t.length())
	{
		if (k == -1 || t[k] == s[i])
		{
			k++;
			i++;
		}
		else
		{
			k = next[k];
		}
	}
	if (k == t.length())
	{
		return i - k;
	}
	else
	{
		return -1;
	}
}

//测试代码
int main()
{
	int Next[20];
	int next[20];
	int k = 0;
	int s = 0;
	k=BF("aaab", "aaaaaabcaaab");
	s = KMP("aaab", "aaaaaabcaaab");
	cout << k;
	FindNext("aaabaacaaadyaccaaabm", Next);
	KMPNext("aaabaacaaadyaccaaabm", next);
	for (int i = 0; i < 20; i++)
	{
		cout << "  " << Next[i];
		cout << "  " << next[i];
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值