简介
处理回文串的小算法
abcba
abccba
从上面两个简单的字符串中可以看出——回文串中心是不确定的:
奇数:有一个字符作为回文串中心;
偶数:有两个字符作为回文串中心;
马拉车采用了非常聪明的小办法解决这个问题——往其中加入中间字符:
变成了(暂且忽略第一个’~'字符)——>
~|a|b|c|b|a|:回文中心为 ‘c’ 字符
~|a|b|c|c|b|a|:回文中心为 ‘|’ 字符
当然,你插入啥字符效果也差不多,看个人爱好
就hen神奇的变成了回文中心只有一个字符了。
说明一下模板题变量的意义看大佬的blog,感觉这样解释好理解一点
cnt:插入字符后串的总长度
p[i] :以i为中心的回文串像某一边最长延伸长度(如a|b|c|b|a,i=5时,相应的p[i]为5)初始化为1(字符本身是个回文串)
mx:当前已判断过的最长回文串的长度
id:mx对应的回文中心
ans:答案——最大的p[i]-1插入了其他字符,一边的长度-1就是答案啦
当下标
s
[
i
]
=
=
s
[
j
]
(
i
<
j
)
s[i] == s[j](i<j)
s[i]==s[j](i<j) 以
i
d
id
id 为中心对称时,
p
[
j
]
p[j]
p[j] 可以由
p
[
i
]
p[i]
p[i] 推出,
p
[
i
]
p[i]
p[i] 同样可以由
p
[
j
]
p[j]
p[j] 推出
当
m
x
>
i
mx>i
mx>i ,即当前下标处于回文串中,与下标
i
i
i 对称的
j
j
j 满足
i
+
j
=
2
×
i
d
i+j=2 \times id
i+j=2×id 。但是!!!要注意
p
[
i
]
+
i
p[i]+i
p[i]+i 一定是小于等于
m
x
mx
mx ,即
p
[
i
]
≤
m
x
−
i
p[i] \leq mx-i
p[i]≤mx−i,两者取下最小值就可以得到
p
[
i
]
p[i]
p[i] 啦
应用
题目
manacher模板题
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1.1e7+10;
char s[maxn<<1], c;
int p[maxn<<1], cnt, mx, id, ans;
inline void initial() {
s[0] = '~'; // 好初始化
s[cnt = 1] = '|';
while (!isalpha(c = getchar())) ;
while (isalpha(c)) {
s[++cnt] = c;
s[++cnt] = '|';
c = getchar();
}
}
int main() {
initial();
for (int i = 1; i <= cnt; i++) {
p[i] = mx > i ? min(p[2*id-i], mx-i) : 1;
while (s[i-p[i]] == s[i+p[i]]) p[i] ++;
if (i + p[i] > mx) {
mx = p[i] + i;
id = i;
}
ans = max(ans, p[i]);
}
printf("%d\n", ans-1);
return 0;
}