每天学习一点点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微服务如何设计异常处理机制?还看不懂算我输

每天学习亿点点day 17: Boyer-Moore 算法和找第K大的数

做了完全看不懂的题之后~

Vue3.0 解读