字符串匹配算法--sunday算法
作者:houskii
链接:https://www.jianshu.com/p/2e6eb7386cd3
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
算法解释
根据上述作者整理得到,有自己的理解
Sunday算法和BM算法稍有不同的是,Sunday算法是从前往后匹配,在匹配失败时关注的是主串中参加匹配的最末位字符的下一位字符。
- 如果该字符没有在模式串中出现则直接跳过,即移动位数 = 模式串长度 + 1;
- 否则,其移动位数 = 模式串长度 - 该字符最右出现的位置(以0开始) = 模式串中该字符最右出现的位置到尾部的距离 + 1。
下面举个例子说明下Sunday算法。假定现在要在主串”substring searching”中查找模式串”search”。
-
刚开始时,把模式串与文主串左边对齐:
Sunday算法1
- 结果发现在第2个字符处发现不匹配,不匹配时关注主串中参加匹配的最末位字符的下一位字符,即标粗的字符
i
,因为模式串search中并不存在i
,所以模式串直接跳过一大片,向右移动位数 = 匹配串长度 + 1 = 6 + 1 = 7,从i
之后的那个字符(即字符n
)开始下一步的匹配,如下图:
Sunday2 -
结果第一个字符就不匹配,再看主串中参加匹配的最末位字符的下一位字符,是’r’,它出现在模式串中的倒数第3位,于是把模式串向右移动3位(m - 3 = 6 - 3 = r 到模式串末尾的距离 + 1 = 2 + 1 =3),使两个’r’对齐,如下:
Sunday3 - 匹配成功。
1 static final int ASCII_SIZE = 126; 2 3 int sunday(char[] total,char[] part){ 4 int tSize = total.length; 5 int pSize = part.length; 6 int[] move = new int[ASCII_SIZE];//这个move[i],i代表的是某个字符对应的int数!!!!!很关键 7 //主串参与匹配最末位字符移动到该位需要移动的位数 8 for (int i= 0;i<ASCII_SIZE;i++){ 9 move[i] = pSize+1; 10 } 11 12 for (int i = 0;i<pSize;i++){ 13 move[part[i]] = pSize-i; 14 } 15 16 int s = 0;//模式串头部在字符串位置 17 18 int j;//模式串已经匹配了的长度 19 20 while(s<=tSize-pSize){//到达末尾之前 21 j = 0; 22 while(total[s+j]==part[j]){ 23 j++; 24 if (j>=pSize){ 25 return s; 26 } 27 } 28 s+=move[total[s+pSize]]; 29 } 30 return -1; 31 }