z函数(扩展kmp)
两个重要的点:1.i - l
2.r
一个简单的证明:
(来源:题解-洛谷P5410 【模板】扩展 KMP(Z 函数) - George1123 - 博客园)
借助前面处理的两个点来避免重复匹配
代码:
void exkmp(string x)//匹配本身
{
l = 0;
lz = x.length();
for (i = 1; i < lz; i++)//最好从1开始,0预处理掉
{
if(i <= r && z[i- l] < r - i + 1)
{
z[i] = z[i - l];
}
else
{
z[i] = max(0,r - i + 1);
while( i + z[i] < lz && x[z[i]] == x[ i + z[i] ] ) z[i]++;
}
if(i + z[i] - 1 > r) l = i,r = i + z[i] - 1;
}
}
注意一个点:
最好是把z[0]和r赋值为0,因为在最下面的if判断里,如果r的初始值为l + z[l] 或者干脆不写r,把r直接换成l + z[l] - 1,当z[l] == maxx且l == 0时,l + z[l]很大,影响更新,拖慢速度
当然不同的题需要特殊判断,这里是同串匹配
关于第一个if:
可以证明:x[i + z[i]] != x[z[i]],因为如果这样,z[i - l]在处理时一定会往后延伸
关于else:
i + z[i] 不能再加1,我当时就犯了这个错
由于l总是最大,匹配的字符总是新的,所以O(n)
浙公网安备 33010602011771号