如果想了解更多内容,欢迎关注我的微信公众号:信息学竞赛从入门到巅峰。
今天,我们来证明一下Manacher的时间复杂度。
先贴上Manacher算法的模板:
s[0] = '$'; s[++m] = '#';
for (b = 1; ss[b] != '\0'; ++b) {
s[++m] = ss[b];
s[++m] = '#';
}
s[++m] = '?';
for (int i = 1; i < m; ++i) {
if (maxid > i) p[i] = min(maxid-i, p[2*id-i]);
else p[i] = 1;
while (s[i-p[i]] == s[i+p[i]]) p[i]++;
if (i + p[i] > maxid) {
maxid = i + p[i];
id = i;
}
}
我们考虑产生复杂度的地方,分别是最外层对整个字符串的遍历和每次对回文串扩展的while。
显然,最外层的for循环是O(N)的,那么我们只需要证明while的总循环次数也是O(N)级别的即可。
很容易发现,每次进入while,回文串的最大覆盖范围都会加1.(为什么呢?)
1、如果以i位置的为回文中心的回文串的基础长度没有超出当前回文串的最大覆盖范围,那么显然不会进入while中(由于对称性,该回文串的长度已经最大了)。
2、如果以i位置的为回文中心的回文串的基础长度超出了当前回文串的最大覆盖范围,那么显然每进入一次while,回文串的最大覆盖范围都会加1.
那么,当最大覆盖范围包含了整个字符串之后,while循环就不会在进入了。所以while循环的总次数为O(N)。
综上所述,Manacher算法的时间复杂度为O(N)。