DS串应用 KMP算法

刚刚搞懂了KMP,输出一下

把长的叫主串,短的叫模式串

KMP,查找字符串的算法,适用于模式串中有重复子串的情况,便于缩短时间

传统暴力解法是模式串一次一次右移,直到对上

主串 Mstr ,模式串 mstr

KMP 主要是 next数组

用一个next数组存储  当模式串中每一个位置失效时对应的next【j】

 kmp其实就是找出已配对成功的部分中的  首尾重复内容来 移动

所以如果尾部的部分不能和前面的部分重叠,

即 mstr【j】 !=mstr【next【j】】,就缩短距离,从前面mstr【0】到mstr【next【j】】的部分再找

找到从str【0】开始的能和 尾部部分重叠的部分,然后获取下标,代替尾部

要是都没有,那就从str【0】开始比较

 

KMP应用

当模式串中某位置 mstr【j】与主串 Mstr【j】不相等时时,对应主串中的位置 Mstr【i】应重新和模式串的 mstr【next【j】】去比较,这样就可以滑动节省时间,特别是模式串长的时候;

eg:  主  ababaccac   模式串abc

                abc                

这里匹配不成功,本来是移动一位,继续比较,但是KMP可以移动俩

在next数组中 next[2]=0,也就是和 模式串mstr【0】 去匹配

(这里是把next【0】放第一个‘a’对应的值,所以‘c' 是next【2】

这样就变成了

       主  ababaccac   模式串abc

                abc                虽然还是没匹配成功,但一次移动距离增大了

eg    主 aaaabababac  模式串 abac

                   abac       

i==6,  j==3 时不成功 ,next【3】=1;    Mastr【6】==’b' 重新和

mstr【next【3】】=b 比较  ,如下 

             aaaabababac

                       abac      

再执行一次,   i==8,  j==3 时不成功 ,next【3】=1;    Mastr【8】==’b' 重新和

mstr【next【3】】=b 比较 

         aaaabababac

                       abac      

恭喜,匹配成功

next值的用途

图片用的我们老师的ppt,这里我借用来记录我的笔记

 

 

如何计算next【】

 

 

对于主串来说 next【j】表示,如果mstr【j】和Mstr【i】匹配不成功,mstr【0】应该移动到

i+1-next【j】;(这个没什么卵用,这个我自己发现的)

对于自身来说,表示,如果mstr【j】匹配成功,那么从0到j-1,首尾存在长度为next【j】个相同的子串(如果下标从1开始,则为next【j】-1)

首先,next【0】=-1;-1是指连第0位匹配失效时,无条件右移

next【1】=0; 第1位匹配不成时,应该重新和模式串头部mstr【0】开始比较

从第二位开始

next【j】受前一位影响 ,且跟mstr【j】本身的值没有关系

 分俩种情况

下面的图片下标从1开始

 

 

代码实现

 

#include <bits/stdc++.h>
using namespace std;
void KMPGETNEXT(){
    string p; cin>>p;
    int l=p.length();
    int next[l];
    next[0]=-1;
    next[1]=0;
    int i=0;
    int j=next[i];//这里用j 表示next【i】的值
    while (i<l)
    {
        if(p[i]==p[j]||j==next[0]){
            next[++i]=++j;
        }
        else
            j=next[j];//如果第一次找不到,那j缩小,找到与p【i】匹配的段
    }
    for (int k = 0; k <l ; ++k) {
        cout<<next[k];
    }
}
int main()
{

    KMPGETNEXT();
}

 

 

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种用于字符匹配的算法,它的核心思想是利用部分匹配表来避免不必要的比较。下面是KMP算法的原理和实现步骤: 1. 部分匹配表的计算: - 部分匹配值是指字符的前缀和后缀的最长公共部分的长度。 - 部分匹配表是一个数组,记录了每个位置的部分匹配值。 - 部分匹配表的计算可以通过动态规划的方式进行,具体步骤如下: - 初始化部分匹配表的第一个元素为0。 - 从第二个元素开始,依次计算每个位置的部分匹配值: - 如果当前位置的字符与前一个位置的部分匹配值对应的字符相等,则部分匹配值加1。 - 如果不相等,则需要回溯到前一个位置的部分匹配值对应的字符的部分匹配值,继续比较。 - 在主中从左到右依次比较字符,同时在模式中根据部分匹配表进行跳跃。 - 如果当前字符匹配成功,则继续比较下一个字符。 - 如果当前字符匹配失败,则根据部分匹配表找到模式中需要跳跃的位置,继续比较。 下面是一个使用KMP算法进行字符匹配的示例代码: ```python def kmp_search(text, pattern): n = len(text) m = len(pattern) next = get_next(pattern) i = 0 j = 0 while i < n and j < m: if j == -1 or text[i] == pattern[j]: i += 1 j += 1 else: j = next[j] if j == m: return i - j else: return -1 def get_next(pattern): m = len(pattern) next = [-1] * m i = 0 j = -1 while i < m - 1: if j == -1 or pattern[i] == pattern[j]: i += 1 j += 1 next[i] = j else: j = next[j] return next ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值