KMP算法
Posted dengschoo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP算法相关的知识,希望对你有一定的参考价值。
KMP算法学习
KMP中用到的函数详解
1. prefix_table()
void prefix_table(char pattern[], int prefix[], int n ) { //用于求取前缀表
prefix[0] = 0; //开始的第一个字符置为0 , 后续函数将数组整体后移
int len = 0;// len指能匹配到的前缀和 和 后缀和的长度
int i = 1; // 从第二个字符开始 pattern的游标
while (i < n) {
if (pattern[i] == pattern[len]) { //如果发现相等
len++; // 匹配长度++
i++; //游标后移
prefix[i] = len; // 第i个字符的前缀表中的值为 len
}
else { //不相等的情况
if (len > 0) // 斜对齐(前缀表整体后移的情况 prefix[0] = -1)
len = prefix[len - 1];
else { // 防止进入死循环
prefix[i] = len;
i++;
}
}
}
}
2. move_prefix_table()
void move_prefix_table (int prefix[], int n) { // 将整个后缀表后移
for (int i = n - 1; i > 0; i++) {
prefix[i] = prefix[i -1];
}
prefix[0] = -1;
}
3. kmp_search()
void kmp_search(char text[], char pattern[]) {
int n = strlen(pattern);
int *prefix = (int *)malloc( sizeof(int) * n);
prefix_table(pattern, prefix, n);
move_prefix_table(prefix, n);
// text[i] len(text) = m
// pattern[j] len(pattern) = n
int i = 0, j = 0;
int m = strlen(text);
int n = strlen(pattern);
while (i < m) {
if ( j == n -1 && text[i] == pattern[j]) { // 匹配到的条件
printf("Found patten at %d.
", i - j); // i - j是子串的起始位置
j = prefix[j]; // 如果多次出现则继续寻找
}
if (text[i] == pattern[j]) { // 正常匹配到则游标右移
i++;
j++;
}
else { //不匹配的情况
j = prefix[j];//将pattern的游标拉到prefix继续匹配
if (j == -1) { // j == -1说明首次未能匹配 则重新开始匹配
i++;
j++;
}
}
}
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void prefix_table(char pattern[], int prefix[], int n ) {
prefix[0] = 0;
int len = 0;
int i = 1;
while (i < n) {
if (pattern[i] == pattern[len]) {
len++;
i++;
prefix[i] = len;
}
else {
if (len > 0)
len = prefix[len - 1];
else {
prefix[i] = len;
i++;
}
}
}
}
void move_prefix_table (int prefix[], int n) {
for (int i = n - 1; i > 0; i++) {
prefix[i] = prefix[i -1];
}
prefix[0] = -1;
}
void kmp_search(char text[], char pattern[]) {
int n = strlen(pattern);
int *prefix = (int *)malloc( sizeof(int) * n);
prefix_table(pattern, prefix, n);
move_prefix_table(prefix, n);
// text[i] len(text) = m
// pattern[j] len(pattern) = n
int i = 0, j = 0;
int m = strlen(text);
int n = strlen(pattern);
while (i < m) {
if ( j == n -1 && text[i] == pattern[j]) {
printf("Found patten at %d.
", i - j);
j = prefix[j];
}
if (text[i] == pattern[j]) {
i++;
j++;
}
else {
j = prefix[j];
if (j == -1) {
i++;
j++;
}
}
}
}
int main() {
char pattern[] = "ABABCABABA";
char text[] = "ABABABCABAABABABAB";
kmp_search(text, pattern);
/*int prefix[9];
int n = 9;
prefix_table(pattern, prefix, n);
move_prefix_table(prefix, n);
for (int i = 0; i < n; i++) {
printf("%d ", prefix[i]);
}
printf("
");*/
return 0;
}
以上是关于KMP算法的主要内容,如果未能解决你的问题,请参考以下文章