每天学习一点点Day 19:KMP完全解读看不懂算我输
Posted Tonarinototoro
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每天学习一点点Day 19:KMP完全解读看不懂算我输相关的知识,希望对你有一定的参考价值。
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]; Array[0]=0; if(m==1) { Array[0]=1; return; } int k=0; int i=1; while(i<=m-1) { if(k>=0&&pattern[k]==pattern[i]) { Array[i++]=++k; } else if(k==0&&pattern[k]!=pattern[i]) { Array[i++]=0; k=0; } else { 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]的值和Array[i-1]密切相关:
所以就三种情况:
一种是Array[i]=k+1;
这个时候就是
以上是关于每天学习一点点Day 19:KMP完全解读看不懂算我输的主要内容,如果未能解决你的问题,请参考以下文章
花了三天整理,Spring Cloud微服务如何设计异常处理机制?还看不懂算我输