KMP算法代码

//先贴代码,简介有空再补
//代码根据 B站UP:正月点灯笼 KMP算法视频编写

B站空间:https://space.bilibili.com/24014925?from=search&seid=10696955474489806893
视频链接:
Part Ⅰ.
Part Ⅱ.

#include<bits/stdc++.h>
#include<string.h>
using namespace std;
/*
对于T子串(待匹配字串)不重复访问字符,即每次比较都是从T的失效位开始的
在pattern中,0到i位的前缀找最大相同前后缀串位数
是为了第i+1位失配时找P的匹配位x,
假设从P的x位开始匹配,
那么P的0到x-1位与T的失配位往前数x位必须是一样的,
就是P的最大相同前缀和后缀,
这就是前缀表。
*/
/*
求前缀表
pattern - 匹配字串
prefix - 前缀表
n - pattern 长度
*/
void prefix_table(char pattern[],int prefix[],int n){
    prefix[0] = 0;//前缀表第一项为0
    int len = 0;//最长公共前后缀的长度
    int i = 1;
    while( i < n){
        cout<<"i = "<<i<<" len = "<<len<<endl;
        if(pattern[i] == pattern[len]){
            len++;
            prefix[i] = len;
            i++;
        }
        else{
            if(len > 0){
                len = prefix[len - 1];
            }
            //如果已经退到边界
            else{
                prefix[i] = len;//此时len = 0
                i++;
            }

        }

    }
}
void prefix_table_move(int prefix[],int n){
    for(int i = n - 1 ; i > 0 ;i --){
        prefix[i] = prefix[i - 1];
    }
    prefix[0] = -1;
}
int kmp_search(char text[],char pattern[]){
    int n = strlen(pattern);
    int m = strlen(text);
    int *prefix = (int *)malloc(sizeof(int) * n);
    prefix_table(pattern,prefix,n);
    prefix_table_move(prefix,n);
    /*
    for(int i = 0 ; i < n;i++){
        cout<<pattern[i]<<" ";
    }
    cout<<endl;
    for(int i = 0 ; i < n;i++){
        cout<<prefix[i]<<" ";
    }
*/
    //text[i] len(text) = m
    //pattern [j] len(pattern) = n
    int i = 0 , j = 0;
    while(i < m && j < n){
        cout<<"i = "<<i <<"j = "<<j<<endl;
            //如果相等
        if(text[i] == pattern[j]){
            i++;
            j++;
        }
            //如果不等
        else{
            j = prefix[j];
            //如果第一个匹配不上,
            if(j == -1){
                i++,j++;
            }
        }
    }
    if(j >= n){
        return i - j;
    }
    else{
        return -1;
    }


}
int main(){
    char text[] = "ABABABAABAABABABAB";
    char pattern[] = "ABABCABAA";
    int prefix[9];
    int n = 9;
    int ans = kmp_search(text,pattern);
    cout<<ans;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值