KMP 算法

KMP 算法是 Knuth、Morris 和 Pra 在 1976 年发表的。它的基本思想是,当出现不匹
配时,就能知晓一部分文本的内容(因为在匹配失败之前它们已经和模式相匹配)。我们
可以利用这些信息避免将指针回退到所有这些已知的字符之前。这样,当出现不匹配时,
可以提前判断如何重新开始查找,而这种判断只取决于模式本身。
推荐网上的几篇比较好的博客,讲的是部分匹配表 (partial match table) 的方法(即
next 数组),“字符串匹配的 KMP 算法”http://t.cn/zTOPfdh,图文并茂,非常通俗易懂,作者
是阮一峰;“KMP 算法详解”http://www.matrix67.com/blog/archives/115,作者是顾森 Matrix67;
”Knuth-Morris-Pra string matching” http://www.ics.uci.edu/ eppstein/161/960227.html。
使用 next 数组的 KMP 算法的 C 语言实现如下。
kmp.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* @brief 计算部分匹配表,即 next 数组.
*
* @param[in] pattern 模式串
* @param[out] next next 数组
* @return 无
*/
void compute_prefix(const char *pattern, int next[]) {
int i;
int j = -1;
const int m = strlen(pattern);
next[0] = j;
for (i = 1; i < m; i++) {
while (j > -1 && pattern[j + 1] != pattern[i]) j = next[j];
if (pattern[i] == pattern[j + 1]) j++;
next[i] = j;
}
}
/*
* @brief KMP 算法.
*
*字符串
* @param[in] text 文本
* @param[in] pattern 模式串
* @return 成功则返回第一次匹配的位置,失败则返回-1
*/
int kmp(const char *text, const char *pattern) {
int i;
int j = -1;
const int n = strlen(text);
const int m = strlen(pattern);
if (n == 0 && m == 0) return 0; /* "","" */
if (m == 0) return 0; /* "a","" */
int *next = (int*)malloc(sizeof(int) * m);
compute_prefix(pattern, next);
for (i = 0; i < n; i++) {
while (j > -1 && pattern[j + 1] != text[i]) j = next[j];
if (text[i] == pattern[j + 1]) j++;
if (j == m - 1) {
free(next);
return i-j;
}
}
free(next);
return -1;
}
int main(int argc, char *argv[]) {
char text[] = "ABC ABCDAB ABCDABCDABDE";
char pattern[] = "ABCDABD";
char *ch = text;
int i = kmp(text, pattern);
if (i >= 0) printf("matched @: %s\n", ch + i);
return 0;
}

 

 

      转发请写明出处   --谢谢

posted @ 2018-05-19 16:04  龙尊  阅读(227)  评论(0)    收藏  举报