您的位置:首页 > 其它

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

2017-09-19 19:58 232 查看

模式匹配:

给定两个字符串 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算法的伪代码:

在串 s 和串 t 中分别设置比较的起始下标j和k;

重复下述操作,直到 s 或 t 的下一对字符;

2.1 如果 s[j]等于 t[k],继续比较二者的下一对字符;

2.2 否则将下标k回溯到next[k]的位置,即k=next[k];

2.3 如果k=-1,则将下标j和k分别加1,准备下一趟比较;

如果 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息