Manacher算法,還有這些你不知道

如果想了解更多內容,歡迎關注我的微信公衆號:信息學競賽從入門到巔峯。

 

今天我們來介紹一下處理迴文字符串的算法:Manacher(俗稱“馬拉車”)。

迴文字符串的通俗定義是:如果一個字符串正着讀或反着讀都一樣,那麼稱這個字符串爲迴文字符串。Manacher的作用就是在O(N)的時間複雜度下求出以每個位置爲迴文中心的迴文半徑。

接下來我們來看看Manacher算法的原理和實現方法吧。

我們還是採用動態規劃的思想,假設0~i的位置的迴文半徑都求出來了,那麼怎麼求第i+1個位置的迴文半徑呢?考慮如果i+1這個位置在被之前覆蓋範圍最遠的一個迴文串包含(假設這個迴文串的迴文中心爲j),那麼i+1關於j對稱的位置(不妨設爲k)就可以轉移到i+1這個位置,給i+1位置的迴文半徑一個初始的值。如果不被之前求過的任意字符串包含的話,那麼顯然爲1(它自己)。

接下來我們要考慮是否i+1位置和k位置的差別。顯然,i+1個位置可能還可以繼續拓展,那麼直接拓展即可(想想時間複雜度爲什麼是對的)。

我們把每個字符作爲迴文中心去處理,那麼很顯然對於長度爲偶數的迴文串無法得到很好的處理,怎麼辦呢?其實我們只要在每個字符中間加入一個該字符串沒有的符號,並且在頭尾加入沒出現過的不同的符號就行了(如下面這個字符串)。

代碼如下:

s[0] = '$'; s[++m] = '#';
for (b = 1; ss[b] != '\0'; ++b) {
    s[++m] = ss[b];
    s[++m] = '#';
}
s[++m] = '?';
for (int i = 1; i < m; ++i) {
    if (maxid > i) p[i] = min(maxid-i, p[2*id-i]);
    else p[i] = 1;
    while (s[i-p[i]] == s[i+p[i]]) p[i]++;
    if (i + p[i] > maxid) {
        maxid = i + p[i];
        id = i;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章