字符串匹配之Sunday算法

        今天做Leetcode的第28题,实现strStr(String haystack, String needle)方法,这个方法需要在haystack中查找needle第一次出现时的index,也就是字符串匹配的问题。本来打算用KMP来实现,但是因为太久没有用这个算法,只有一个模糊的印象,关于失败函数的求法有点生疏,于是上网找博客,偶然发现了一篇博客提到了好几个算法,其中的Sunday算法据说是容易理解和编码,于是查了一下,也学习了这篇关于Sunday算法的博客:http://kmplayer.iteye.com/blog/704187

       Sunday算法的原理也很容易理解,先上代码:

public int findMatch(String source, String pattern) {
        char src[] = source.toCharArray();
        char des[] = pattern.toCharArray();
        int len_s = src.length, len_d = des.length, pos = 0, i = 0, j = 0;
        if(0 == len_d && 0 == len_s)
            return 0;
        int next[] = new int[26];
        // 初始化数组为len_d+1,如果某个字符c不存在于pattern中,则需要从这个字符的下一个开始和pattern比较
        for(; i < 26; i ++) 
            next[i] = len_d + 1;  
        // 记录pattern中的每一个字符离最右端的距离,如果一个字符出现多次,则最后一次出现的距离会作为最终值
        for(i = 0; i < len_d; i++)
            next[des[i] - 'a'] = len_d - i;
        
        while(pos <= len_s-len_d) {
            i = pos;
            j = 0;
            for(; j < len_d; i++, j++) {
                // 从pos处和pattern的字符逐个比较,如果不等则移动pos指针
                if(src[i] != des[j]) {
                    if(pos+len_d >= len_s)
                        return -1; // 已近不存在下一个可以移动到的字符位置了,所以没找到
                    pos += next[src[pos+len_d]-'a'];  //判断src[pos+len_d]是否存在于pattern中,存在则移动相应位置,否则移动pattern长度+1
                    break;
                }
            }
            // 如果相等则证明查找倒了匹配字符
            if(j == len_d)
                return pos;
        }
        return -1;
}

       在Sunday算法进行匹配之前要预处理一下字符串needle,求出每个字符离最右端的距离,例如对于字符串abcdec,a离最右端的距离是6,b是5,需要注意的是c,我们必须要取字符串最右边一个c离最右端的距离进行存储,因为在匹配失败的时候是移动到右边第一个匹配的字符,因此左边相同字符的距离都没有意义。把预处理的结果存储在数组next中,如果字母不存在与needle中,例如对于abcdec,x是不存在于其中的,那么x离needle最右端的距离为needle长度+1,因为匹配失败可以直接跳过一个needle长度的子串。




你可能感兴趣的:(字符串匹配之Sunday算法)