字符串匹配Sunday算法C++实现

字符串匹配Sunday算法

sunday算法简介

Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。其核心思想是:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率(算法思想很简单)。在一定程度上比KMP算法和BM算法更优。但是该算法最坏情况下的时间复杂度为O(m*n)。 
Sunday的算法思想和Horspool有些相似,但是。当出现不匹配的时候,却不是去找匹配串中不匹配的字符在模式串的位置,而是直接找最右边对齐的右一位的那个字符在模式串的位置。

sunday算法原理

这里写图片描述 
举个栗子:设字符串为 THIS IS A SIMPLE EXAMPLE,搜索词为EXAMPLE如图所示。 
1.这里写图片描述 
第一次匹配过程中,从搜索词的首字母开始从左往右匹配,字符串中的“H”与 “E”发现不匹配,就查找字符串中右端对齐的字符的下一位,也就是“ ”(空格),原则:如果该字符没有在匹配串中出现则直接跳过,即移动步长= 匹配串长度+1;否则,同BM算法一样其移动步长=匹配串中最右端的该字符到末尾的距离+1。

2.这里写图片描述 
发现字符串与搜索词右端对齐的下一位字符即“ ”(空格)并不在搜索词中出现过,就移动步长为8位,如图所示。

3.这里写图片描述 
继续从左往右开始匹配字符,发现字符串中的“A”与搜索词中的“E”并不匹配,就查看右端对齐的下一个字符“E”,发现“E”在搜索词中,并且有两个,按照suanday原则就选择搜索词中最右的字符“E”,这样可以保证在右端对齐的下以一个字符在搜索词中存在的情况下,移动步长最小,保证这种情况下不失匹配机会。 
移动后,从左往右开始匹配,发现是“ ”(空格)与搜索词的首字母“E”不匹配,继续按上述匹配原则进行移动。 
4. 
这里写图片描述 
字符串与搜索词最右端的下一个字符是“ ”(空格),依照上述原则,在搜索词中并不存在“ ”(空格),移动的步长为8,最终结果如图所示。

下面是我写的代码:

int indexShift(const string s,const char ch) {
	for (int k1(0); k1 < s.length(); ++k1) {
		if (ch == s[k1]) return -k1;
	}
	return 1;
}

vector<int> sunday(const string s1, const string s2) {
	vector<int> ret;
	int sl1(s1.length()), sl2(s2.length());
	if (!(sl1 && sl2))return ret;
	for (int k1(0), k2(0); k1 <= sl1 - sl2;) {
		if (s1[k1] == s2[k2]) ++k1, ++k2;
		else {
			k1 += sl2 - k2;
			k1 += k1 < sl1 ? indexShift(s2, s1[k1]) : 0;
			k2 = 0;
		}
		if (k2 == sl2) ret.push_back(k1 - k2), k1 -= k2 - 1, k2 = 0;
	}
	return ret;
}

由于算法很容易理解,这里不多做阐述。


posted @ 2017-05-13 23:01  lmjy  阅读(263)  评论(0编辑  收藏  举报