KMP的Next数组应用总结

Next数组求法

不用初始化,因为Next数组是递推出来的。用法为getFail(s,strlen(s)).

const int MAX_N=101000;
char str[MAX_N],pattern[MAX_N];
int Next[MAX_N];
void getFail(char *p,int plen){
    int i;
    Next[0]=0;Next[1]=0;
    for(i=1;i<plen;i++){
        int j=Next[i];
        while(j&&p[i]!=p[j])
            j=Next[j];
        Next[i+1]=(p[i]==p[j])?j+1:0;
    }
}

囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖
学习笔记
KMP的Next数组可以求一个字符串的最小循环节,如果它有的话。
循环节长度 x=len-Next[len]。
比如ababab,x为2
abbcabbcabbc,x为3
但是如果是abba的话x为3,如果想要求这个字符串的最小循环节长度再加一个判断条件即可,
即如果len%x!=0的话x=len。
像abba,x应该为len,即为4.
像abbabba,x应该为7,abbabbab,x为8,abbabbabb,x为3,因为它可以整除了。
另一个问题,如果一个字符串,我最少需要添加多少个字符才可以出现2个及以上的循环。
添加字符之后的字符串的最小循环节长度为len-Next[len]。
那么答案即为(len-Next[len])-len%(len-Next[len])。
可以看成(循环节)-字符串长度%(循环节)。
定理如果一个字符串有循环节的话且循环节且总长度可以整除循环节,即没有末尾循环节破损,那么最小循环节长度为len-Next[len],如果循环节破损,那么在没法添加字符的条件下最小循环节长度即为字符串本身长度len,而在可以添加字符的条件下,如果想要添加字符串数量最少,那么添加完之后字符串的最小循环节为len-Next[len]。

囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖

利用Next数组求字符串的前缀在字符串中出现的次数。
利用dp,dp[i]代表字符串的第1个字符到第i个字符这个子串出现在字符串中的次数(字符串下标从1开始,方便),这个出现次数是可重复的,比如aaaaa的dp[2]为4。
dp数组求法

int len=strlen(s);
getFail(s,len);
for(i=1;i<=len;i++)
 dp[i]=1;
for(i=len;i>=1;i--)
 dp[Next[i]]+=dp[i];

小思维:
求字符串a的每个前缀在b中出现的次数。
可以把构建一个字符串c=a+’#’+b,然后求出dp_c,然后再求出dp_a,那么答案就为dp_c[i]-dp_a[i]。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值