AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

KMP算法

作者: 作者的头像   water-lover ,  2020-08-13 09:47:49 ,  所有人可见 ,  阅读 881


2


BF算法

朴素做法, 简单粗暴, 易于理解

平均时间复杂度$O(n + m)$

最坏时间复杂度$O(n * m)$

int index_BF(string s, string t, int pos){
    int i = pos, j = 1;
    while(i <= s.length() && j <= t.length()){
        if(s[i] == t[j]) ++ i, ++ j;
        else i = i - j + 2, j = 1;
    }
    if(j > t.length()) return i - t.length();
    return 0;
}

公共前后缀

公共前后缀的条件:
1. 最长的公共前后缀
2. 不包含字符串本身

KMP算法

BF改进算法,同样易于实现, 重点在于next函数的设计.

时间复杂度$O(n + m)$

KMP算法 — 模板1

next[i] = j的含义为:
含义1. 模板串第 i 个字母与主串对应字母不匹配时,模板串下一个要与主串对应字母匹配的位置为 j
含义2. next[i] = j, 表示 t[1, j - 1] = t[i - j + 1, i - 1], 即以 i 结尾的最长公共前后缀的长度为 j - 1

next函数

void get_next(string t, int next[]){
    int i = 1, j = 0;
    ne[1] = 0;
    while(i <= t.length()){//得包括计算ne[n + 1]的值,也可以不计算ne[n + 1]
        if(j == 0 || t[i] == t[j]) ++ j, ++ i, ne[i] = j;
        else j = ne[j];
    }
}

改进后的next函数

void get_next(string t, int next[]){
    int i = 1, j = 0;
    ne[1] = 0;
    while(i <= t.length()){//得包括计算ne[n + 1]的值, 
        if(j == 0 || t[i] == t[j]){
            ++ j, ++ i;
            if(t[i] != t[j]) ne[i] = j;
            else ne[i] = ne[j];
        }
        else j = ne[j];
    }
}

KMP算法 ---- 成功匹配一次后结束

int  index_kmp(string s, string t, int pos){
    int i = pos, j = 1;
    while(i <= s.length() && j <= t.length()){
        if(j == 0 || s[i] == t[j]) ++ i, ++ j;
        else j = ne[j];
    }
    if(j > t.length()) return i - t.length();
    return 0;
}

KMP算法 ---- 成功匹配多次后结束

void kmp(string s, string t, int pos){
    int i = pos, j = 1;
    while(i <= s.length() && j <= t.length()){
        if(j == 0 || s[i] == t[j]) ++ i, ++ j;
        else j = ne[j];
        if(j > t.length(){//匹配成功
            cout << i - t.length() << ' ';//输出第一次匹配成功的位置
            j = ne[j];//为下一次匹配做准备
        }
    }
}

KMP算法 — 模板2

next[i] = j的含义为:
含义1. 模板串第 i 个字母与主串对应字母不匹配时,模板串下一个要与主串对应字母匹配的位置为 j + 1
含义2. next[i] = j, 表示 t[1, j] = t[i - j + 1, i], 即以 i 结尾的最长公共前后缀的长度为 j

next函数

//next函数
void get_next(char t[], int ne[]){
    for(int i = 2, j = 0; i <= lent; i ++){
        while(j && t[i] != t[j + 1]) j = ne[j];
        if(t[i] == t[j + 1]) j ++;
        ne[i] = j;
    }
}

KMP算法 ---- 成功匹配一次后结束

//kmp算法, 匹配过程
int  index_kmp(char s[], char t[]){
    for(int i = 1, j = 0; i <= lens; i ++){
        while(j && s[i] != t[j + 1]) j = ne[j];
        if(s[i] == t[j + 1]) j ++;
    }
    if(j == lent) return i - lent + 1;
    return 0
}

KMP算法 ---- 成功匹配多次后结束

//kmp算法, 匹配过程
void kmp(char s[], char t[]){
    for(int i = 1, j = 0; i <= lens; i ++){
        while(j && s[i] != t[j + 1]) j = ne[j];
        if(s[i] == t[j + 1]) j ++;
        if(j == lent){//匹配成功
            cout << i - lent + 1<< ' ';
            j = ne[j];
        }
    }
}

经典试题

KMP字符串

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息