zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    CheckBox单选功能
    DOTNET
    常用命令行
    不能调试的问题的解决
    url字符串中含有中文的处理
    案例:星移eWorkflow.net系统
    使用正则表达式求完整路径中的文件名
    缺少一个***.resource的报告的解决
    Mapx中的图元移动
    Distance计算的距离随经纬度不同
  • 原文地址:https://www.cnblogs.com/DengSchoo/p/12662727.html
Copyright © 2011-2022 走看看