重要圖片
源代碼
int Manacher()
{
int len = Init(); // 取得新字符串長度並完成向 s_new 的轉換
int max_len = -1; // 最長迴文長度
int id; // 以id中心的最長迴文
int mx = 0; // b邊界
for (int i = 1; i < len; i++)
{
// 如果i在列表右邊界內,那麼就比較i的對稱點j 和mx-i 的大小
if (i < mx)
p[i] = min(p[2 * id - i], mx - i);
else
p[i] = 1;
while (s_new[i - p[i]] == s_new[i + p[i]]) // 不需邊界判斷,因爲左有'$',右有'\0'
p[i]++;//無法使用if (i < mx)來判斷,只能比較i兩邊的對應值是否相等
// 我們每走一步 i,都要和 mx 比較,我們希望 mx 儘可能的遠,
// 這樣才能更有機會執行 if (i < mx)這句代碼,從而提高效率
if (mx < i + p[i]) // 超過mx邊界的i+p[i],邊界mx 需要重新賦值
{
id = i;
mx = i + p[i];
}
max_len = max(max_len, p[i] - 1); // 通過比較每個元素的p[i]和max_len的大小,更新max_len的值
}
return max_len;
}
代碼分析
p[i] = min(p[2 * id - i], mx - i);
mx-i 和 2*id-i是爲了防止i和j 的向左右擴展 ???會不會同時向兩邊擴展