KMP算法

一、可以解决的问题
字符串匹配的问题
在这里插入图片描述
时间复杂度:O(m*n)
m为文本串的长度
n为模式串的长度
二、前缀表

三、前缀和后缀
字符串:aabaaf
前缀:包含首字母不包含尾字母的所有子串
前缀有
a
aa
aab
aaba
aabaa
后缀:包含尾字母不包含首字母的所有字串
后缀有
f
af
aaf
baaf
abaaf

四、最长相等(公共)前后缀
字符串:aabaaf
子串 前缀 后缀 最长相等前后缀
a 无 无 无
aa a a 1
aab a/aa b/ab 0
aaba a/aa/aab a/ab/aba 1
aabaa a/aa/aab/aaba a/aa/baa/abaa 2
aabaaf a/aa/aab/aaba/aabaa f/af/aaf/baaf/abaaf 0

五、使用前缀表匹配的过程

六、代码实现
next数组:一般是前缀表右移或者前缀表数值减一
因为在模式串的每一个位置都可能发生不匹配,也就是说我们要计算每一个位置j对应的k,所以用一个数组next来保存,next[j] = k,表示当T[i] != P[j]时,j指针的下一个位置。另一个非常有用且恒等的定义,因为下标从0开始的,k值实际是j位前的子串的最大重复子串的长度。T-文本串,P-模式串
主要分为两步:
(一)计算前缀表
(二)根据前缀表移动两个指针进行匹配
求next数组(前缀表减一的形式)

void getNext(int* next, const string& s){
    int j = -1;
    next[0] = j;
    for(int i = 1; i < s.size(); i++) { // 注意i从1开始
        while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
            j = next[j]; // 向前回退
        }
        if (s[i] == s[j + 1]) { // 找到相同的前后缀
            j++;
        }
        next[i] = j; // 将j(前缀的长度)赋给next[i]
    }
}

使用next数组来做匹配

int j = -1; // 因为next数组里记录的起始位置为-1
for (int i = 0; i < s.size(); i++) { // 注意i就从0开始
    while(j >= 0 && s[i] != t[j + 1]) { // 不匹配
        j = next[j]; // j 寻找之前匹配的位置
    }
    if (s[i] == t[j + 1]) { // 匹配,j和i同时向后移动
        j++; // i的增加在for循环里
    }
    if (j == (t.size() - 1) ) { // 文本串s里出现了模式串t
        return (i - t.size() + 1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值