効果
文字列の各位置で最長のパリンドローム文字列を計算することは、すべてのパリンドローム間隔を計算するとも言えます。
原理
アルゴリズムは、拡張配列を見つけるためのkmpの拡張と非常に似ていると思います。
間隔のパリティ長に関する議論を避けるために、最初の位置に「$」を挿入して0未満の議論を避け、次に各文字の間に「#」を挿入します。
len [i]を使用して、位置iで最長の回文構造の右半分の長さを表します。上記の処理により、ここでの間隔の右半分の長さは、元のストリングの回文構造の間隔の全長です。
計算中に到達した右端の境界をpとする。aはpに対応する位置を表します。iがaと対称な位置は2 * a-iです。i + len [2 * a-i]がpの範囲を超えない場合、len [i] = len [2 * a-i]になります。それ以外の場合は、pとaを拡張して更新します。
void mana() {
ios::sync_with_stdio(false);
s.clear();
ans.clear();
s.push_back('$');
s.push_back('#');
for(int i = 0; ss[i]; i++) {
s.push_back(ss[i]);
s.push_back('#');
}
int a = 1, p = 1;
for(int i = 1; i < s.size(); i++) {
if(i < p && len[2 * a - i] < p - i) len[i] = len[2 * a - i];
else {
int l = p - i;
while(i + l < s.size() && s[i + l] == s[i - l]) l++;
len[i] = l;
a = i;
p = i + l;
}
}
}