扩展 KMP(Z 函数)

扩展 KMP(Z 函数)

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

问题一

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

考虑到 [l,r]=[1,rl+1] 所以 i[l,r][i,r]=[il+1,rl+1]

因此,求 z(i) 可以利用到 z(il+1),即 z(i)min{z(il+1),ri+1}

分类讨论:

  1. ir
    1. z(il+1)<ri+1z(i)=z(il+1)
    2. z(il+1)ri+1 则令 z(i)=ri+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 (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 次。

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

问题二

我们要解决的问题为:求 ba 每一个后缀的 LCP

b+a 拼起来做就可以了。

posted @   chzhc  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
levels of contents
点击右上角即可分享
微信分享提示