前缀函数与KMP

前缀函数
定义:
一个长度为n的字符串s,其前缀函数被定义为一个长度为n的数组Π,其中Π[i]的定义是:

  1. 如果子串s[0…i]有一对相等的真前缀与真后缀,即存在s[0,k-1]=s[i-(k-1),i],那么Π[i]就是这个相等的真前缀的长度k,得到Π[i]=k
  2. 如果不止一对相等,Π[i]=max(k)
  3. 如果没有相等的,那么Π[i]=0

用于优化的性质:
相邻的前缀函数值至多增加1,增加条件为s[i+1]==s[Π[i]],所以当移动到下一个位置时,前缀函数的值要么增加1,要么维持不变,要么减少,循环可以从期望最大值开始
当s[i+1]!=s[Π[i]],失配时如何跳转?失配时,我们找到对于子串s[0…i],仅次于Π[i]的第二长度j,使得在位置i的前缀性质仍得以保持,即[s…j-1]==s[i-(j-1)…i],此时比较s[i+1]和s[j],如果相等则得到Π[i+1]=j+1;否则,找到再次一级的长度,依次推类,直至满足条件。
关于j的状态转移方程:
j n = π [ j n − 1 − 1 ] j^{n}=\pi \left[ j^{n-1}-1\right] jn=π[jn11]

最终算法如下:

// C++ Version
vector<int> prefix_function(string s) {
   
  int n = (int)s.length();
  vector<int> pi(n);
  for (int i = 1; i < n; i++) 
  {
   
    int j = pi[i - 1];
    while (j > 0 && s[i] != s[j]) 
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值