Z函数(扩展KMP)

Z函数(扩展KMP)

用于解决以下问题:给定一个长度为n的字符串s,求出一个数组z,其中zi表示字符串s(0,n1)s(i,n1)的最长公共前缀。其中 |s|<=2×107

假设当前已经求出了z0zi1,下一个要求zi

p1i1中,能匹配到的最远距离,即:p=max(j+zj1),j[1,i1],记p取最大值时j的值为k.

可知:字符串s(0,zk1)s(k,k+zk1)是相等的.

假设此时要求的i[k,k+zk1],可知s(i,k+zk1)s(ik,zk1)是相等的。

l=zik, 则s(0,l1)s(ik,ik+l1)是相等的. 又因为s(ik,ik+l1)s(i,i+l1)是相等的,因此我们找到了从i开始的一段长为l的公共前缀.下面分两种情况:

1.当i+l1p时,zi的值即为l.

2.当i+l1p时,大于p的部分不一定能和前面匹配上,因此应该从p开始往后扩展.

算法的复杂度为O(n),n为字符串的长度.

代码
const int N = 20000005;
int n, z[N];
string s;
void Z(string &s) {
    n = s.size();
    int p = 0, k = 1; z[0] = n;
    while(z[1] + 1 < n && (s[z[1] + 1] == s[z[1]])) z[1]++;
    p = z[1]; k = 1;
    for(int i = 2; i < n; i++) {
        int l = z[i - k];
        if(i + l - 1 <= p) {
            z[i] = l;
        } else {
            z[i] = max(0, p - i + 1);
            while(z[i] + i < n && (s[z[i] + i] == s[z[i]])) z[i]++;
        }
        if(z[i] > p) {
            p = z[i]; k = i;
        }
    }
}
posted @   Mcggvc  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示