• KMP 各版本实现代码


    /*
    * DA-Main-KMP.cpp
    *
    * 两种版本, 每个版本的 找一个子串 及 找所有子串
    *
    * 教材版 : 《数据结构域算法》 高等教育出版社 张铭等著 2008版
    * 算法导论版 :《算法导论》第二版 及 《数据结构域算法》2004版
    *
    * Created on: 2011-11-14
    */
    #include <iostream>
    #include <cstring>
    using namespace std;


    char Pattern[200], Str[200];
    int next[200];

    ////////////////////////////////////////////
    //教材版
    ////////////////////////////////////////////
    void preKMP(char *P){ //优化
    int j, k;
    int len = strlen(P);

    next[0] = -1;
    j = 0, k = -1;
    while(j < len - 1){
    while(k >= 0 && P[j] != P[k]){
    k = next[k];
    }
    k++, j++;

    //不注的话是优化版
    // if(P[j] != P[k])
    next[j] = k;
    // else
    // next[j] = next[k];
    }
    }



    int KMP_1(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    i = start, j = 0;
    while(i < tLen && j < pLen){
    while(j >= 0 && T[i] != P[j]){
    j = next[j];
    }
    i++, j++;
    }
    if(j >= pLen)
    return i - pLen;
    return -1;
    }

    int KMP_2(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    i = start, j = 0;
    while(i < tLen && j < pLen){
    if(j == -1 || T[i] == P[j])
    i++, j++;
    else
    j = next[j];
    }
    if(j >= pLen)
    return i - pLen;
    return -1;
    }

    //找所有子串
    void KMP_3(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    i = start, j = 0;
    while(i < tLen){
    while(j >= 0 && T[i] != P[j]){
    j = next[j];
    }

    if(j == pLen - 1){
    cout << i - j << endl;
    j = next[j];
    }
    else //注意加else!!!!!!!!!!!!!!!!!!!!!!!!!!!
    i++, j++;
    }
    }

    void KMP_4(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    i = start, j = 0;
    while(i < tLen){
    if(j == -1 || T[i] == P[j]){
    if(j == pLen - 1){
    cout << i - j << endl;
    j = next[j];
    }
    else
    i++, j++;
    }
    else
    j = next[j];
    }
    }


    ////////////////////////////////////////
    //算法导论版\04教材版 (注意 算法导论 中下标从1开始, 所以有所不同)
    ////////////////////////////////////////

    void preKMP_CLRS(char *P){
    int j, k;
    int pLen = strlen(P);

    next[0] = 0;
    for(j=1; j<pLen; j++){
    k = next[j-1];
    while(k > 0 && P[j] != P[k])
    k = next[k-1]; //下标从0开始,所以长度 = 下标 +1
    if(P[j] == P[k])
    k++;
    next[j] = k;
    }
    }


    int KMP_CLRS(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    j = 0;
    for(i=start; i<tLen; i++){
    while(j > 0 && T[i] != P[j]){
    j = next[j-1];
    }
    if(T[i] == P[j])
    j++;
    if(j == pLen)
    return i - j + 1;
    }
    return -1;
    }

    //找所有子串
    void KMP_CLRS_2(char *T, char *P, int start){
    int i, j;
    int tLen = strlen(T);
    int pLen = strlen(P);

    j = 0;
    for(i=start; i<tLen; i++){
    while(j > 0 && T[i] != P[j]){
    j = next[j-1];
    }
    if(T[i] == P[j]){
    if(j == pLen - 1){
    cout << i - j << endl;
    j = next[j];
    j--; //注意:长度 = 下标 + 1
    }
    j++;
    }
    }
    }





    void test(){
    cin >> Str >> Pattern;

    preKMP(Pattern);

    cout << "next : " << endl;
    for(int i=0; i<strlen(Pattern); i++)
    cout << next[i] << "";
    cout << endl << endl;


    cout << KMP_1(Str, Pattern, 0) << endl;
    cout << KMP_2(Str, Pattern, 0) << endl;

    cout << endl;
    KMP_3(Str, Pattern, 0);
    cout << endl;
    KMP_4(Str, Pattern, 0);
    cout << endl;

    /////////////////////////////////
    preKMP_CLRS(Pattern);

    cout << "next_CLRS : " << endl;
    for(int i=0; i<strlen(Pattern); i++)
    cout << next[i] << "";
    cout << endl << endl;

    cout << KMP_CLRS(Str, Pattern, 0) << endl;
    cout << endl;
    KMP_CLRS_2(Str, Pattern, 0);


    }

    int main(){

    test();



    return 0;
    }



  • 相关阅读:
    Mybatis各种模糊查询
    ORACLE查询当前资产状态,和另一个数据库联查,(查询重复数据中第一条),子查询作为字段查询
    驱动文件操作
    驱动开发中使用安全字符串函数
    驱动开发 判断内存是否可读 可写
    驱动模式使用__try __excpet
    简单解释Windows如何使用FS段寄存器
    手动载入NT驱动
    PUSHA/PUSHAD
    跳转指令公式计算 HOOK
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2249029.html
Copyright © 2020-2023  润新知