Sunday算法不像KMP算法那么复杂,但是效率又比较高,在KMP之上,下面简单介绍Sunday算法及其实现。
Sunday 算法由 Daniel M.Sunday 在 1990 年提出,它的思想跟 BM 算法很相似:
只不过 Sunday 算法是从前往后匹配,在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。
如果该字符没有在模式串中出现则直接跳过,即移动位数 = 匹配串长度 + 1;
否则,其移动位数 = 模式串中最右端的该字符到末尾的距离 +1,使得下一位字符与模式串中与其相等的字符对齐。
下面举个例子说明下 Sunday 算法。假定现在要在文本串"substring searching algorithm"中查找模式串"search"。
1.刚开始时,把模式串与文本串左边对齐:
2.结果发现在第 2 个字符处发现不匹配,不匹配时关注文本串中参加匹配的最末位字符的下一位字符,即标粗的字符 i,因为模式串 search 中并不存在 i,
所以模式串直接跳过一大片,向右移动位数 = 匹配串长度 + 1 = 6 + 1 = 7,从 i 之后的那个字符(即字符 n)开始下一步的匹配,如下图:
3.结果第一个字符就不匹配,再看文本串中参加匹配的最末位字符的下一位字符,是‘r‘,它出现在模式串中的倒数第3位,于是把模式串向右移动 3 位(r 到模式串末尾的距离 + 1 = 2 + 1 =3),使两个‘r‘对齐,如下:
4.匹配成功。
下面是Sunday算法的javascript实现
function sunday(source, pattern) { var sLen = source.length, pLen = pattern.length; var sIndex = 0, pIndex = 0, loc = 0; while (sIndex < sLen && pIndex < pLen) { //索引相等,向后继续比对 if (source[sIndex] == pattern[pIndex]) { sIndex++; pIndex++; } else { //not equal,jump var aimChar = source[sIndex + pLen], pAim = pLen - 1; //找索引,与参与匹配的串的下一位的值相等的字符在模式串中的索引 while (pAim > 0) { if (aimChar == pattern[pAim]) { break; } pAim--; } //jump,pLen - pAim就是sIndex应该前进的值,sIndex从0算起 sIndex += pLen - pAim; //record location loc = sIndex; //reset to zero pIndex = 0; } } if (pIndex < pLen) { return -1; } return loc; }
由于Sunday算法每一步的移动量都比较大,因此效率很高。
参考:http://wiki.jikexueyuan.com/project/kmp-algorithm/sunday.html
http://blog.csdn.net/silver_sail/article/details/8137782