ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

扩展 KMP(Z 函数)

2022-07-30 15:32:50  阅读:145  来源: 互联网

标签:函数 LCP 扩展 循环 KMP nS operatorname


扩展 KMP(Z 函数)

下文用 \([a, b]\) 表示 \(s[a \to b]\),\((l, r)\) 表示当前 \(r\) 最右的匹配段。

问题一

要解决的问题为:求出 \(z\) 函数,\(z(i) = \operatorname{LCP}(s[i, nS], s[1, nS])\),其中 \(\operatorname {LCP}(a, b)\) 表示 \(a, b\) 的最长相同前缀。

考虑到 \([l, r] = [1, r - l +1]\) 所以 \(\forall i \in [l, r]\) 有 \([i, r] = [i - l + 1, r - l + 1]\)。

因此,求 \(z(i)\) 可以利用到 \(z(i - l + 1)\),即 \(z(i) \geq \min\{ z(i - l + 1), r - i + 1\}\)。

分类讨论:

  1. \(i \leq r\)
    1. 若 \(z(i - l + 1) < r - i + 1\) 则 \(z(i) = z(i - l + 1)\);
    2. 若 \(z(i - l + 1) \geq r - i + 1\) 则令 \(z(i) = r - i + 1\) 然后往后扩展。
  2. \(i > r\) 则令 \(z(i) = 0\) 然后向后扩展。

由此可以写出代码:

nS = strlen(s + 1);
l = 0, r = 0;
for (int i = 2; i <= nS; ++ i)
{
	if (i <= r && z[i - l + 1] < r - i + 1)
		z[i] = z[i - l + 1];
	else 
    {
        z[i] = std::max(r - i + 1, 0);
		while (1 + z[i] <= nS && i + z[i] <= nS && s[1 + z[i]] == s[i + z[i]])
			z[i] ++;
    }
	if (i + z[i] - 1 > r)
		l = i, r = i + z[i] - 1;
}

显然,外层循环只会循环 \(nS\) 次,而内层 while 循环每循环一次必使得 \(r\) 增大,\(r\) 顶多增大到 \(nS\),故内层循环顶多进行 \(nS\) 次。

综上所述,时间复杂度为 \(\mathcal O(n)\)。

问题二

我们要解决的问题为:求 \(b\) 与 \(a\) 每一个后缀的 \(\operatorname{LCP}\)。

把 \(b + a\) 拼起来做就可以了。

标签:函数,LCP,扩展,循环,KMP,nS,operatorname
来源: https://www.cnblogs.com/chzhc-/p/16535082.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有