Sunday算法简介
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法。就是为了确定一个字符串是否包含指定的字符串。
平均时间复杂度:O(n)。
最坏情况下时间复杂度为:O(nm)。
算法分析
其核心思想是:Sunday算法是从前往后匹配,在匹配过程中,模式串(pattern)发现不匹配时,在匹配失败时关注的是主串(main)中参加匹配的最末位字符的下一位字符。
1、如果模式串中没有该字符则直接跳过,即移动位数 = 模式串长度 + 1;
2、如果模式串中有该字符,即移动位数 = 该字符在主串中的位置 - 模式串中该字符最后一次出现的位置。目的是让该字符与模式串中的字符对齐,再从前往后比较每个字符。
贴上JavaScript代码
function sunday(main,pattern,ignoreCase)
{
var charSet = {}, //存放模式串 pattern 的每个字符最后一次出现的位置
patternLen = pattern.length,//模式串 pattern 的长度
mainLen = main.length; //主串 main 的场地
//是否忽略大小写
if(ignoreCase) {
main = main.toLowerCase();
pattern = pattern.toLowerCase();
}
//存下 pattern 中每个字符的位置,出现重复字符时:后面出现的字符的位置将会覆盖前面出现的字符的位置
for (var i = 0; i < patternLen; i++) {
charSet[pattern.charAt(i)] = i;
}
//主串与模式串逐个比较
for (var i = 0; i <= mainLen-patternLen; ) {
var j = 0;
//比较主串与模式串对应的字符,相同则往后移动一位,注意 i 始终没有变,只是加上了 j 表示移动位置
while(j<patternLen && main.charAt(i+j) == pattern.charAt(j)) {
j++;
}
if(j == patternLen) {
return i;//在主串 main 中找到了子串 pattern,返回 pattern 在主串中的位置
} else {
var next = i + patternLen, //主串中与模式串对应的最后一个字符的下一个字符
charPos = charSet[main.charAt(next)];//next所对应的字符在 charSet 的位置,没有返回undefined
if(charPos > -1) { //模式串中存在next对应的字符
i = next - charPos; //让主串与模式串中相同的字符对齐
} else {
i = next + 1;//模式串中没有 next 对应的字符,主串直接跳过该字符,i 跳到 next 的下一位
}
}
}
return -1;//主串main中没有匹配的子串pattern,返回 -1
}