您的位置:首页 > 其它

比KMP更简单更有意思的Sunday算法

2016-09-27 23:15 197 查看
一般想到字符串的匹配算法,大家很快就会想到KMP,毕竟教科书上都是介绍它相关的内容,但是前面在准备面试的过程中,发现了一种效率不比它差,但是简单易懂的算法。感觉这种算法确实很有意思。

首先两个字符串

例如:在eaabb babadbbcd 中找adcbb

首先

eaabb babadbbcd :i A

adcbb :j B

对齐,然后一个一个匹配:得出在index为0,1,2的位置均相等,

eaabb babadbbcd

adcbb

但是index 位2的位置不相等,sunday算法的基本思路是

【1】找跳转指示:不匹配的时候,看较长的字符串中对齐后冒出了的第一个字符,这里就是b。

【2】根据指示字符找出能够跳的最大步数,尽可能的往后面跳,这里的这个字符是b,然后具体怎么跳:

如果个字符不在短的字符串中出现,说明我前面和现再所处的这个字符,在我要匹配的字符串中没有,那我就直接跳过你,在你的后面开始重新匹配。比如这里的b改成z,就直接把短的给对齐到z后面。

eaabbbabadbbcd i=7 指示a

__ _adcbb j=0指示 a

如果出现就把短字符串的最后出现b(为什么是最后出现,因为你看下面的例子,如果是前一个b对齐,那么i就跳得更远,而最后对齐这种潜在的可能匹配的情况就被忽略掉了)的位置和这个指示位置对齐。当然还是从头开始匹配,接下来看他们的前面那部分是否相等,,为什么这么对齐,因为这么对齐后可能会出现匹配,相对于一次跳一步这种方法可以尽可能的排除去不可能的情况。

efcabcbabadbbcd i=2 指示c

__adcbb j=0指示a

public static int SundayMatch(String str,String patten){
int len1=str.length();
int len2=patten.length();
int[] map=new int[256];
for(int i=0;i<256;i++){
map[i]=-1;
}
for(int i=0;i<len2;i++){//如果有相同的,显然就保存了最后一个字符的index
map[patten.charAt(i)]=i;
}
for(int i=0;i<len1-len2;){
int j=0;//每次跳完后j都是0
while(j<len2){
if(str.charAt(i)==patten.charAt(j)){
i++;
j++;
}else{  //一遇到不匹配就往后跳
int index=i+len2-j;//跳到不匹配的第一个字符,index表示它的位置
char p=str.charAt(index);
if(map[p]==-1){   //如果str中没有这个字符i直接跳
i=index+1;    //不管你前面了就直接跳到后面
}else {
i=index-map[p];//index-1 - (map[p]-1) 前者表示对齐后长字符串的最后一个字符,后者表示还要往前看map[p]-1个字符是否匹配
//由于map[p]表示p在短字符中的index如b的最后一个index=5的话,i就必须往前看4个字符
}
break;
}
}
if (j == len2) {
return i - len2;//匹配完后停留在尾端,和头相差len2的距离
}
}
return -1;


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: