• 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;
    }
    
    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;
    }
    
  • 相关阅读:
    Mysql关键字冲突的解决方案
    js日期时间函数
    Mysql字符串字段中是否包含某个字符串,用 find_in_set
    mysql中 where in 用法
    Best of Best系列(4)——AAAI
    Best of Best系列(5)——IJCAI
    Best of Best系列(3)——ICML
    Best of Best系列(6)——SIGIR
    Best of Best系列(2)——ICCV
    Best of Best系列(1)——CVPR
  • 原文地址:https://www.cnblogs.com/DengSchoo/p/12662727.html
Copyright © 2020-2023  润新知