算法描述与证明

cpp
for (int i = 1; i <= m; i++) { // 遍历预处理后的字符串t
p[i] = 1; // 初始化最小回文半径为1(单个字符)
if (maxid > i) // 如果i在当前最右回文边界内
p[i] = min(p[2 * id - i], maxid - i); // 利用对称性快速确定下限
// 暴力扩展回文半径
while (t[i - p[i]] == t[i + p[i]])
p[i]++; // 若两侧字符相等,半径+1
// 更新最右回文边界及中心
if (i + p[i] > maxid) {
id = i;
maxid = i + p[i];
}
}
部分代码分析
cpp
while(t[i-p[i]] == t[i+p[i]])
p[i]++;
这段代码是看在当前以 i 为中心(如果超出了)最大范围外的左边和右边是否相等,如果相等说明可以进一步扩展,将当前回文半径加一。
cpp
if(maxid > i)
p[i] = min(p[2 * id - i], maxid - i);
这段代码是,如果当前点在当前最大回文子串的范围内,找当前点的以当前最大回文子串中心点的对称点(以当前最大回文子串中心点折过去所对应的点)和当前点到当前最大回文子串右边界的距离的最小值。因为串对称过来以后超过当前最大回文子串右边界的话,超出的部分就不能对称过来了(不能保证左侧超出的部分和右侧超出的部分相同)。所以要取两者最小值。
完整流程
| 步骤 | 操作 | 目的 |
|---|---|---|
| 1 | 预处理字符串(插入#和哨兵) |
统一奇偶回文为奇数长度 |
| 2 | 初始化p[i]=1 |
每个字符至少自身是回文 |
| 3 | 利用对称性快速确定下限p[i] = min(p[j], maxid-i) |
跳过重复比较,优化效率 |
| 4 | 暴力扩展while(...) p[i]++ |
验证并扩大回文半径 |
| 5 | 更新maxid和id |
维护当前最右回文边界信息 |