定义一个长度为 n 的字符串 s,定义 zi 表示s 和s[i,n] 的lcp(最长公共前缀),称 z 为s 的Z 函数。朴素算法暴力枚举,时间复杂度:O(n2)线性算法我们首先考虑顺次处理 z1,z2,…,zn,当枚举到 i 时,也就是说 z1,…,zi−1 是已经求得了。我们再来定义名词 Z-box :指与字符串 s 匹配的前缀区间...
对于一个长度为 nn 的字符串 ss,定义函数 z[i]z[i] 表示ss 和s[i,n−1]s[i,n−1](即以 s[i]s[i] 开头的后缀)的最长公共前缀(LCP)的长度,则 zz 被称为 ss 的Z 函数。特别地,z[0]=0z[0]=0。国外一般将计算该数组的算法称为 Z Algorithm,而国内则称其为 扩展KMP。
voidexKMP(char*s){intn=(int)strlen(s+1);z[1]=0;for(inti=2,l=0,r=0;i<=n;i++){if(i<=r&&z[i-l+1]<r-i+1)z[i]=z[i-l+1];else{z[i]=std::max(0,r-i+1);while(i+z[i]<=n&&s[z[i]+1]==s[i+z[i]])z[i]++;}if(i+z[i]-1>r){l=i;r=i+z[i]-1;...
通过Z-box,我们很好地利用了我们之前获得的信息。 根据z函数的定义,我们知道若z[i]=x,则从i位置开始,结束于i+x-1的字符串(记作{z[i]-z[i+x-1]})与字符串{z[0]-z[x-1]}是完全相同的,而且z[x]与z[i+x]是不一样的——否则就不满足最大公共前缀这一要求了。 那么,在匹配过程中,我们会出现...
Z 函数的求法 根据Z 函数的定义,我们可以枚举待求字符串的的每一个后缀,从头开始尝试匹配,得到 Z 函数的值。这样计算的时间复杂度是O(n2)O(n2)。 参考代码(std::string,字符串下标从0开始): voidGetZFunc(conststd::stringstr){intlen = str.length();for(inti =1; i < len; i++)while(i + z...
扩展KMP(Z 函数)学习笔记,扩展$KMP$就是对于两个字符串$s1,s2$,求$s1$的每一个后缀和$s2$的$LCP$长度。个人感觉明明叫$ExKMP$却和$KMP$毫无关系,反而与$Manacher$有着异曲同工之妙。
视频中用到的网站 https://personal.utdallas.edu/~besp/demo/John2010/z-algorithm.htm字符串 abababzabababab---题解 + Python/Java/C++/Go 代码:Q1 https://leetcode.cn/problems/ant-on-the-boundary/solution/tong-ji-qian-zhu, 视频播放量 7369、弹幕量 25、点赞数 2
z[i] = z[i-p0]; else { now = max( p0+z[p0]-i,0 ); while( now+i<pl && p[now]==p[now+i] ) now++; z[i] = now; p0 = i; } } } void exkmp() { getZ(); int now = 0, p0 = 0; while( now<pl && now<sl && p[now]==s[now] ) now++; ...
视频地址:【koko的算法课堂】KMP匹配、Z函数、扩展KMP 铁傀儡的二代 粉丝:13文章:1 关注 题目大意 已知str1和str2分别为主串和模式串,求str所有子串中和模式串相等的串的下标位置(这个一求出来,个数也就迎刃而解了) 首先KMP分为两步 1.求模式串配对 ...
Z 函数的朴素算法复杂度为 :实现 C++Python 1 2 3 4 5 6 7 vector<int> z_function_trivial(string s) { int n = (int)s.length(); vector<int> z(n); for (int i = 1; i < n; ++i) while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; return z; } ...