【洛谷】P4555 [国家集训队]最长双回文串
P4555 [国家集训队]最长双回文串
题源:https://www.luogu.com.cn/problem/P4555
原理:Manacher
还真比KMP好理解
解决最长回文串问题
转化为长度为奇数的回文串
原串长度 = 新串长度半径 - 1
1. 转化:首位加不同字符,中间加 #
(图片源自AcWing)
2. 求p[i]:以 \(s_i\) 为中心的最大回文串的半径(含中心)
3. 最大半径 - 1 即为所求
注意要用char数组,因为string是动态扩容的,很有可能访问到非法边界
板子:
void init (){
int k = 0;
b[k ++] = '$', b[k ++] = '#';
for (int i = 0; i < a.size(); i ++)
b[k ++] = a[i], b[k ++] = '#';
b[k ++] = '^';
n = k;
}//心里要有张图,构造的时候可不能错
void manacher (){
init();
int mr = 0, mid;
for (int i = 1; i < n; i ++){
if (i < mr)
p[i] = min (mr - i, p[2 * mid - i]);
else
p[i] = 1;//超过边界就不是回文了
while (b[i + p[i]] == b[i - p[i]])
p[i] ++;
if (i + p[i] > mr)
mr = i + p[i], mid = i;//找到更大的串了,更新边界
ans = max (ans, p[i] - 1);
}
}
思路
一会儿再肝~