KMP

记录
18:16 2024-2-5

目录

1.KMP


先把我之前学时候的笔记拉过来 数据结构学习第二十三天

串的模式匹配(KMP算法)

给定一段文本,从中找出某个指定的关键字

目标

  给定一段文本:$ string=s_0s_1.....s_{n-1}$

  给定一个模式:$ pattern=p_0p_1......p_{m-1}$

  求\(pattern\)\(string\)中出现的位置

简单实现

  方法1:c的库函数 strstr

简单改进

  方法2:从末尾开始比

大师改进

  方法3:KMP(Knuth、Morris、Pratt)算法

  将时间复杂度从\(T=O(nm) 改进到 T=O(n+m)\)

$ match(j)=\begin{cases} 满足p_0.....p_i=p_{j-i}....p_j的最大i(<j) \ -1 如果这样的i不存在 \end{cases} $

KMP算法 (这算法惊艳到我了)

总的来说,在每次比较失败时 下一次到可以匹配的时候是将已经匹配成功的序列中 从头开始的与从尾开始子列中可以匹配的最大部分 将头部移动到尾部 再进行比较 这样的话 对于给定的string文本的指针 不会向后移动 使得这个算法高效

之前写的

点击查看代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define NotFound -1

typedef int Position;

void BuildMatch(char* pattern, int* match)
{
    Position i, j;
    int m = strlen(pattern);
    match[0] = -1;
    for (j = 1; j < m; j++)
    {
        i = match[j - 1];
        while (i >= 0 && pattern[i + 1] != pattern[j])
            i = match[i];
        if (pattern[i + 1] == pattern[j])
            match[j] = i + 1;
        else
            match[j] = -1;
    }
}

Position KMP(char* string, char* pattern)
{
    int n = strlen(string);
    int m = strlen(pattern);
    Position s, p, * match;

    if (n < m)return NotFound;
    match = (Position*)malloc(sizeof(Position) * m);
    BuildMatch(pattern, match);
    s = p = 0;
    while (s<n&&p<m)
    {
        if (string[s] == pattern[p])
        {
            s++; p++;
        }
        else if (p > 0)
            p = match[p - 1] + 1;
        else
            s++;
    }
    return (p == m) ? (s - m) : NotFound;
}

int main()
{
    char string[] = "This is a simple example";
    char pattern[] = "simple";
    Position p = KMP(string, pattern);
    if (p == NotFound)printf("Not Found.\n");
    else printf("%s\n", string + p);
    return 0;
}


书上比较简便的写法, 字符串下标从1开始,到n结束,即[1,n]

点击查看代码
// KMP
next[1] = 0;
for (int i = 2, j = 0; i <= n; i++) {
	while (j > 0 && a[i] != a[j+1]) j = next[j];
	if (a[i] == a[j+1]) j++;
	next[i] = j;
}

for (int i = 1, j = 0; i <= m; i++) {
	while (j > 0 && (j == n || b[i] != a[j+1])) j = next[j];
	if (b[i] == a[j+1]) j++;
	f[i] = j;
	// if (f[i] == n),此时就是A在B中的某一次出现
}

// KMP 下标从0开始
next[0] = -1;
for (int i = 1, j = -1; i < N; i++) {
    while (j >= 0 && str[i] != str[j+1]) j = next[j];
    if (str[i] == str[j+1]) j++;
    next[i] = j;
}

for (int i = 0, j = -1; i < M; i++) {
	while (j >= 0 && (j == n - 1 || tar[i] != str[j+1])) j = next[j];
	if (tar[i] == str[j+1]) j++;
	f[i] = j;
	// if (f[i] == n - 1),此时就是A在B中的某一次出现
}

posted @ 2024-02-21 16:55  57one  阅读(9)  评论(0编辑  收藏  举报