2021-05-24

kmp中next数组的建立

kmp算法中最难的莫过于next数组的构建,刚学的时候看了代码也和sb一样不知道咋回事,只能靠背下来,过几天又忘记😅,(确实拉胯),最近似乎理解了,记个笔记。

其实啊,next数组的构建是dp算法实现的(怎么就没人说呢,我害推了半天卧槽)。

先设要求的字符串为str,既然是dp,那么第一步:

int dp[1000] = {0,};//dp[i]指从str[0]-str[i]闭区间中的最长相等前后缀。
memset(dp,-1,sizeof(dp));

dp中最重要的就是递推公式的推导了,接下来推一下递推公式。
比如当str="abcabcg"时。
我们取两个指针,一个i先指向str[0],j指向str[1]。
第一步:很明显str[0]不等于str[1],所以我们令dp[1]=-1,然后j++,向第三个字符前进
第二步:和第一步一样依旧i,j的指向值不相等
于是j++找第四个字符
第三步:同第二步j++
第四步:我们发现i,j指向的值相同了,那么就要进行与上面稍有不同的操作了,此时的最长相等前后缀明眼人都看出来了吧,就是1,于是dp[j]=1-1,这里也i++,为下一步准备(这里可以自己写一写体会一下为什么要i++)
第五步:动态规划的特点是存储之前的状态为下面的服务,基于这个思想,我们向前寻找是否有可以利用的值。此时求的是dp[4],也就是"abcab"的最长相等前后缀,而我们的dp[3]是"abca"的最长相等前后缀,所以粗略确定与dp[3]有关,通过观察,dp[4]本应该是"ab"长度,而dp[3]已经有了"a"的长度,那么只要比较str[i]与str[j],发现相同,我们直接dp[3]+1就可以了。到现在,我们初步得出的公式有

if(str[i]==str[j]) dp[j]=dp[j-1]+1;
i++;

第六步:我们可以通过这一步验证一下刚才得到的公式,发现正确,进行与上面第五步相同的操作
第七步:我们又发现i,j指向的值又不同了,那么又有与上方不同的操作了。
此时算的是abcabcg的最长相等前后缀,一看就知道它没有,如何计算呢?
这里的计算方法要自己推一下,这里给出我的方法
计算方法:此时的i指向str[3],j指向str[7],发现不同,将i退回0,j不变,如果str[i]与str[j]还是不同,那么就说明[0,7]一个相等前后缀都没有,dp[j]赋值-1,j++;如果相同赋值0,i++,j++;
最后抽象出代码:
什么阴间代码编辑器。。。

#include<iostream>
#include<string>
#include<memory>
int main(){
    int dp[1000] = {0,};
    memset(dp,-1,sizeof(dp));
    string str;    
    cin >> str;   
     int len = str.size();    
    for(int i = 0,j = 1;j < len;j++)    
    {        if(str[i] == str[j])       
            {            
                  dp[j] = dp[j-1] + 1;           
                   i++;                    
             } 
              else      
             {        
                  i = 0;           
                   if(str[i] == str[j])           
                    {                
                       dp[j] = 0;             
                       i++;    
                     }        
             }        
               cout << dp[j]<<' ';    
    }    
               return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值