从BF算法到KMP算法(字符串匹配算法)

来源:互联网 发布:欧朋安卓浏览器开启js 编辑:程序博客网 时间:2024/04/29 21:11

模式匹配:

给定两个字符串 s= "..."和 t="...",在主串 s 中查找子串 t 的过程称为模式匹配,匹配成功,则返回t在s中的位置,否则返回-1;

BF算法

  • 比较简单,相对效率比较低的字符串匹配算法,时间复杂度为O(m*n);
  • 基本思想:从主串 s 的第一个字符开始和子串 t 的第一个字符串开始比较,若相等,则继续比较二者后续字符; 若不相等,从主串的第二个字符和子串的第一个字符比较,重复上述步骤直至 s 或 t 中的字符比较完毕,这样很容易用代码描述出来
    public int bf(String str, String pattern) {        char[] c = str.toCharArray();        char[] p = pattern.toCharArray();        int j = 0, k = 0;        while (j < c.length && k < p.length) {            if (c[j] == p[k]) {                j++;                k++;            } else {                j = j - k + 1;                k = 0;            }        }        if (k == p.length) {            return j - k;        } else            return -1;    }

KMP算法

BF算法简单,但效率较低,一种对BF算法做了比较大的改进的匹配算法是KMP算法,其基本思想是主串不回溯
  • 定义:Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。
  • KMP算法的伪代码:
    1. 在串 s 和串 t 中分别设置比较的起始下标j和k;
    2. 重复下述操作,直到 s 或 t 的下一对字符;
      2.1 如果 s[j]等于 t[k],继续比较二者的下一对字符;
      2.2 否则将下标k回溯到next[k]的位置,即k=next[k];
      2.3 如果k=-1,则将下标j和k分别加1,准备下一趟比较;
    3. 如果 t 中多有字符均比较完毕,则返回匹配开始的位置,否则返回-1;
  • KMP算法难点就在于求next数组
  • next数组:为子串前缀集合和后缀集合中相同串中长度最大的数组集合,如下图

给出子串ababc,求出next数组

这里写图片描述

所以next[] = {-1, 0, 0, 1, 2}

实现代码如下

public int[] getNext(String p) {        char[] t = p.toCharArray();        int[] next = new int[t.length];        int j = 0, k = -1;        next[0] = -1;        while (j < t.length - 1) {            if ((k == -1) || (t[j] == t[k])) {                next[++j] = ++k;            } else                k = next[k];        }        return next;    }

KMP算法代码如下

public int kmp(String str, String pattern) {        int next[] = getNext(pattern);        char[] c = str.toCharArray();        char[] p = pattern.toCharArray();        int j = 0;// 主串位置        int k = 0;// 模式串位置        while (j < c.length && k < p.length) {            if (k == -1 || c[j] == p[k]) {                j++;                k++;            } else {                k = next[k];            }        }        if (k == p.length) {            return j - k;        } else            return -1;    }
原创粉丝点击