1. 程式人生 > 其它 >Manacher 學習筆記

Manacher 學習筆記

if(2 * maxn - i >= 1)	
    f[i] = min(f[2 * maxn - i],maxr - i);
else	
    f[i] = maxr - i;

關於這個演算法,最難以理解的部分也就這裡,也就是判斷 \(i\) 的最長迴文長度的下界。

首先定義 \(j\)\(i\) 關於 \(maxn\) 的對稱點,\(mxr\) 為已有迴文半徑覆蓋到的最右點\(maxn\) 為其的中心點

首先關於 \(j\) 的尋找,因為 \(maxn = \frac{i-j}{2}\),所以可以化簡得:\(2\times maxn = i - j\),所以 \(j = 2\times maxn - i\)

關於第一行的判斷條件,也就是在判斷 \(j\) 的存在,然後看後面的兩種情況。

1:若 \(f[j] < maxr - i\),我們選擇的下界會是 \(f[j]\),則有下圖

​ 其中用紅線代表 \(i,j\) 的迴文範圍,\(maxr- i\) 也就是 \(i\)\(maxr\) 的距離。首先因為這一長段都是以 \(maxn\) 為中心的迴文子串,所以其實以 \(j\) 為中心的迴文子串也在以 \(i\) 為中心的迴文子串那裡(不一定完整),因為 \(j\) 的迴文半徑小於 \(i\)\(maxr\) 的距離,所以以 \(j\) 為中心的整個迴文串都完整地到了 \(i\)

的地方,所以對於 \(i\) 來說它的迴文半徑的下界也就是 \(j\) 的迴文半徑。之所以說是下界,因為超過這個下界的 \(i\) 的右邊可能有一些值仍然可以和 \(i\) 的左邊匹配,因為超過部分不一定和 \(j\) 那裡一樣,所以是下界。

2:若 \(f[j] > maxr - i\),我們選擇的下界會是 \(maxr - i\),則有下圖:

此時也就相當於 \(j\) 的迴文半徑的長度超過了 \(maxn\) 的限制,也就是以 \(j\) 為中心的迴文串只有一部分因為 $maxn $ 的限制而來到了 \(i\) 的位置,而這一部分的長度也就是 $j $ 到 $maxn $ 限制的左端點的距離,也就是 \(maxr - i\)

那麼因為這一段有 \(maxn\) 的限制再加上在 \(j\) 是會問的,所以也一定是迴文的