為了方便分析,用字元 '#』 表示空字元,那麼對於字串 s = "aabcdefg",可以表示成 _s = "#a#a#b#c#d#e#f#g#"。顯然,對於長度為n的字串s,可能的回文串的中心有n + (n + 1) = 2 * n + 1個,即原字元數加#字元數。
遍歷每乙個可能的中心點,以該中心點為基礎,生成回文串,即若兩末端字元相等,則回文串向兩端生長,直到兩末端字元不相等,結束生長,得到以該點為中心的最長回文串。如此可以得到每個可能中心點的最長回文串,選取最長的返回。
**:
class solution
public string centerexpand(string s)
}return s.substring(start, end + 1);
}//在s中從i到j已經是回文串,試圖讓該回文串繼續生長至最長,返回長度
public int expandstring(string s, int i, int j)
return j - i - 1;}}
我覺得這個演算法是對中心擴充套件法的乙個改進。中心擴充套件法遍歷每乙個可能的中心,並求出以該中心代表的最長回文串,具體做法是讓該中心向兩邊生長至不能生長為止。manacher演算法同樣是如此。
改進在於,中心擴充套件法的初始中心是乙個字元,要麼是原字串中的乙個字元,要麼是『#』(空字元),而manacher演算法可能是這樣,也可能是乙個有幾個字元的回文串。所以,區別就是,manacher演算法在呼叫expandstring函式時,引數可能不是(s, i, i),而是(s, l, r),問題變成了,你怎麼知道s中從l到r是以i為中心的回文串?
起初,對於乙個中心i,我們知道i到i是以i為中心的回文串,所以我們有了中心擴充套件演算法。現在,對於乙個中心i,我們知道l到r是以i為中心的回文串,所以我們有了manacher演算法,這兩種演算法的核心思想都一樣,如果明白第一種做法,那明白第二種做法就只需要明白l和r怎麼求。
現在我們來弄明白怎麼求l和r
首先假設我們用中心擴充套件演算法求解求了一半,如圖,用線段表示字串 _s:
s1和s2都是已經求出的回文串,s2包含在s1的左半部分,顯然,s1右半部分有乙個s2的翻轉串,又因為s2是回文串,翻轉後依然是s2,假設翻轉過去的s2的中心點剛好是i,那麼翻轉過去的s2左右端點下標就是我們需要的l和r
以l到r為中心去擴充套件,顯然比以i到i為中心去擴充套件節約時間。
具體做法是,用c記錄s1的中心下標,r表示s1的最右端下標,這樣就可以唯一表示乙個s1,顯然,r越大越好,所以每次求出乙個最長回文串,就維護一下r和c。為了儲存s2之流的資訊,我們開闢乙個陣列radius[i],radius[i]代表以i為中心的最長回文串長度的一半,顯然中心擴充套件演算法radius[i]初始全為1,而manacher演算法初始化為math.min(radius[2 * c - i], r - i + 1)或者1,接著借radius[i],求出l和r
**:
class solution
public string manacher(string s)
//更新表示s1的c和r
if(i + radius[i] - 1 > r)
}//把最長回文串中的字元'#'去掉再返回 ps:要是用python我會寫這種又臭又長的**?
stringbuffer ans = new stringbuffer();
for(int i = start; i <= end; i++)
}return ans.tostring();
}//同上
public int expandstring(string s, int i, int j)
return j - i - 1;
}//在字串s的縫隙裡插入字元'#',返回 ps:要是用python我會寫這種又臭又長的**?
public string manacherstring(string s)
return _s.tostring();}}
回文串之中心擴充套件法
中心擴充套件法可以幫助減少在回文子串中暴力遍歷的一次迴圈,在普通暴力遍歷中,我們需要兩次迴圈分別確定左指標和右指標 即回文子串的左右邊界 然後還有一次迴圈向中間靠攏判斷。中心擴充套件法將向中心靠攏的這一步改為了由中心向兩邊延申,由於回文子串有奇數和偶數之分,所以中心擴充套件法的起始點需要分兩種情況討...
最長回文子串,中心擴充套件法 C語言
給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb 因為是找回文子串,所以使用中心擴充套件法,中心擴充套件有兩種,一種是以單個字元 i,i 為中心,乙個是...
演算法訓練 最長回文子串(中心擴充套件演算法)
問題描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。示例1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例2 輸入 cbbd 輸出 bb 這是leetcode的一道關於字串的題,在官方給出的題解有5種思路,分別是 最長公共子串 暴力法...