ACM练习-KMP
字符串匹配算法(KMP)
构造前缀表
首先对子串构造前缀表
// 求每个前缀的最长公共前后缀
void prefix_table(char pattern[], int prefix[], int n)
{
prefix[0] = 0;
int len = 0, i = 1;
while (i < n) {
// 如果相等则公共前后缀长度加1
if (pattern[len] == pattern[i]) {
len++;
prefix[i] = len;
i++;
}
else {
if (len > 0) {
len = prefix[--len];
}
else {
// 没有公共前后缀
prefix[i] = 0;
++i;
}
}
}
}
// 将前缀表往后移动一格
void move_prefix(int prefix[], int n)
{
for (int i = n - 1; i > 0; --i) {
prefix[i] = prefix[i - 1];
}
prefix[0] = -1;
}
根据前缀表进行字符串匹配
void kmp_search(
const char* text, int m,
const char* pattern, int n)
{
int* prefix = (int*)malloc(sizeof(int) * n);
prefix_table(pattern, prefix, n);
move_prefix(prefix, n);
// kmp search
int i = 0, j = 0;
for (; i < m;) {
if (j == n - 1 && text[i] == pattern[j]) {
printf("found \"%s\" at %d\n", pattern, i - j);
j = prefix[j];
}
if (text[i] == pattern[j]) {
i++; j++;
}
else {
j = prefix[j];
if (j == -1) {
i++; j++;
}
}
}
free(prefix);
}
KMP算法测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR_LEN 256
int main(int argc, char** argv)
{
int m, n;
char text[MAX_STR_LEN];
char pattern[MAX_STR_LEN];
scanf("%s", text);
scanf("%s", pattern);
m = strlen(text);
n = strlen(pattern);
kmp_search(text, m, pattern, n);
return 0;
}
程序运行结果
输入:
ABABABCABAABABABAB
ABABCABAA
输出:
found “ABABCABAA” at 2