KMP算法详解

在做题时,碰到了一个在A串中寻找B串的题目,如果在A串中可以找到B串,则返回B串首次出现时的下标,否则返回-1。一开始,我用的是最Naive的方法,时间复杂度为O(MN),其中M为A串长度,N为B串长度。代码如下:

    int Index(string s, string t, int pos) { // 从pos开始搜索
        int i = pos, j = 0, sl = (int)s.length(), tl = (int)t.length();
        while (i<sl && j<tl) {
            if (s[i] == t[j]) { // 继续比较后面的字符
                i++;
                j++;
            } else { // i和j回退,重新进行比较
                i = i-j+1;
                j=0;
            }
        }
        if (j == tl) {
            return i-tl;
        } else {
            return -1;
        }
    }
其实还有更好的方法,那就是KMP算法。KMP算法的时间复杂度为O(M+N),空间复杂度为O(N)。KMP的核心思想请参考严蔚敏《数据结构》第80页。程序代码如下:

    void get_next(string& t, int next[]) {
        int i = 0, tl = (int)t.length(), j = -1;
        next[0] = -1; // next[0]=-1的意思是,下一步应该拿i+1与j=0相比。
        while (i < tl) {
            if (j == -1 || t[j] == t[i]) {
                j++;
                i++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    }
    int Index(string s, string t, int pos) {
        int i = pos, j = 0, sl = (int)s.length(), tl = (int)t.length();
        int next[tl];
        get_next(t, next); // 得到next数组
        while (i<sl && j<tl) {
            if (j == -1 || s[i] == t[j]) { // 继续进行比较,若j == -1,则说明j第一个字符就与i不相等,则j第一个字符与i+1相比
                i++;
                j++;
            } else {
                j=next[j]; // 如果j和i不相等,则j回退到next[j]再与i进行比较
            }
        }
        if (j == tl) {
            return i-tl;
        } else {
            return -1;
        }
    }

对于get_next函数,还有可以优化的地方。如下:

    void get_next(string& t, int next[]) {
        int i = 0, tl = (int)t.length(), j = -1;
        next[0] = -1; // next[0]
        while (i < tl) {
            if (j == -1 || t[j] == t[i]) {
                j++;
                i++;
                if (t[i] != t[j]) { // 如果t[i]和t[next[j]]不相等,则next[i]=j,否则next[i]=next[j]
                    next[i] = j;
                } else {
                    next[i] = next[j];
                }
            } else {
                j = next[j];
            }
        }
    }


阅读更多
个人分类: leetcode
上一篇27. Remove Element
下一篇29. Divide Two Integers
想对作者说点什么? 我来说一句

KMP算法详解 KMP算法详解

2010年08月10日 33KB 下载

KMP算法详解KMP算法详解

2011年03月19日 51KB 下载

KMP算法详解 KMP算法详解

2010年04月15日 26KB 下载

模式匹配的KMP算法详解.

2011年07月08日 34KB 下载

没有更多推荐了,返回首页

关闭
关闭