ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

每天学习一点点Day 19:KMP完全解读看不懂算我输

2021-06-09 23:04:41  阅读:233  来源: 互联网

标签:子串 字符 19 pattern 公共 int KMP Array Day


1. KMP 实际上相对于Boyer Moore算法来看,实际上只使用了一个启发性算法,那就是找公共子串(左边是以开头为前缀,右边是以最后一个字符为后缀),通过这个公共子串就可以减少一些不必要的比较.

2. 我觉得大部分人应该也和我一样一开始最搞不懂的就是shift表怎么求的吧?

实际上网上很多解释都没有把一些事情用白话说清楚, 因为你上来就Next数组,i,j啊啥的,其实很多小伙伴就蒙了。。。。

那么我这里先定义一下,我这个版本的数组的内容是:

Array[i]: 指的是在一个pattern串里从0到下标为i的字符(包括Pattern[i]这个字符)形成的字符串里,

最长的公共子串: 这个公共子串指的是以pattern[0]为前缀,和以pattern[i]为后缀的字符串的最长公共子串

以abcabc为例子

Array[4]=2;

这里的最长公共子串就是abcab

标黑的部分
实际上等我们把这个计算出来了,接下来就是算在i位置上匹配失败时应该移动多少距离: 已经匹配成功的字符数-Array[i].

其实就是先算一下公共子串长度,然后利用这个信息再算实际要怎么移动!简单吧?

那么我们其他地方就不提直接看Array怎么算吧?

直接上代码:

void CalPrepArray(string & pattern, int* Array)
{
    
    int m=pattern.length();
    int *tmp=new int[m];
//第一个字符一定是0 Array[0]=0;
//如果pattern只有一个字符, 直接就可以知道最后结果 if(m==1) { Array[0]=1; return; } int k=0; int i=1;
// 默认上一次的最长结果为0
//i从1开始数, 0已经计算过了 while(i<=m-1) { if(k>=0&&pattern[k]==pattern[i]) {
//发现有之前的结果可以利用 Array[i++]=++k; } else if(k==0&&pattern[k]!=pattern[i]) {
// 避免k=0的时候Array[k-1[访问越界 Array[i++]=0; k=0; } else {
//为啥这里是k-1你大概明白吧?k是上一次最长公共子串的长度Array是根据位置来算的所以才是k-1
k=Array[k-1]; } } //后面就不解释了 for(int i=0;i<m;i++) { tmp[i]=Array[i]; } for(int i=0;i<m;i++) { if(i==0||i==1) { Array[i]=1; } else Array[i]=i-tmp[i-1]; cout<<Array[i]<<endl; } delete[] tmp; }

很多人可能理解不了k的含义到底是啥?

其实就是上一次也就是Array[i-1]的结果. 因为我们发现Array[i]的值和上一次的最长公共串的结果有关.

其中可能不太好理解的就是回溯是怎么做的

 

 

 

 懂了吧?是不是很简单, 剩下的东西我放源码注释里了,挺简单的.

标签:子串,字符,19,pattern,公共,int,KMP,Array,Day
来源: https://www.cnblogs.com/Tonarinototoro/p/14869217.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有