題目描述:現給定乙個已知的字串str,現在想要在o(n)的時間複雜度之內求出乙個最長的回文子字串(正著和倒著順序讀一致)。
演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法——kmp和拓展kmp,這次來還是來總結乙個字串演算法,manacher演算法,我習慣叫他 「馬拉車」演算法。
相對於前面介紹的兩個
演算法,manacher
演算法的應用範圍要狹窄得多,但是它的思想和拓展kmp
演算法有很多共通支出,所以在這裡介紹一下。
manacher
演算法是查詢乙個字串的最長回文子串的線性演算法。
在介紹演算法之前,首先介紹一下什麼是回文串,所謂回文串,簡單來說就是正著讀和反著讀都是一樣的字串,比如abba,noon等等,乙個字串的最長回文子串即為這個字串的子串中,是回文串的最長的那個。
下面介紹manacher演算法的原理與步驟。
首先,manacher演算法提供了一種巧妙地辦法,將長度為奇數的回文串和長度為偶數的回文串一起考慮,具體做法是,在原字串的每個相鄰兩個字元中間插入乙個分隔符,同時在首尾也要新增乙個分隔符,分隔符的要求是不在原串中出現,一般情況下可以用#號。下面舉乙個例子:
manacher演算法用乙個輔助陣列len[i]表示以字元t[i]為中心的最長回文字串的最右字元到t[i]的長度,比如以t[i]為中心的最長回文字串是t[l,r],那麼len[i]=r-i+1。
對於上面的例子,可以得出len[i]陣列為:
len陣列有乙個性質,那就是len[i]-1就是該回文子串在原字串s中的長度,至於證明,首先在轉換得到的字串t中,所有的回文字串的長度都為奇數,那麼對於以t[i]為中心的最長回文字串,其長度就為2*len[i]-1,經過觀察可知,t中所有的回文子串,其中分隔符的數量一定比其他字元的數量多1,也就是有len[i]個分隔符,剩下len[i]-1個字元來自原字串,所以該回文串在原字串中的長度就為len[i]-1。
首先從左往右依次計算len[i],當計算len[i]時,len[j](0<=j
第一種情況:i<=p
那麼找到i相對於po的對稱位置,設為j,那麼如果len[j]
那麼說明以j為中心的回文串一定在以po為中心的回文串的內部,且j和i關於位置po對稱,由回文串的定義可知,乙個回文串反過來還是乙個回文串,所以以i為中心的回文串的長度至少和以j為中心的回文串一樣,即len[i]>=len[j]。因為len[j]
如果len[j]>=p-i,由對稱性,說明以i為中心的回文串可能會延伸到p之外,而大於p的部分我們還沒有進行匹配,所以要從p+1位置開始乙個乙個進行匹配,直到發生失配,從而更新p和對應的po以及len[i]。
第二種情況: i>p
如果i比p還要大,說明對於中點為i的回文串還一點都沒有匹配,這個時候,就只能老老實實地乙個乙個匹配了,匹配完成後要更新p的位置和對應的po以及len[i]。
**實現
public static voidmain(string args)
public static int
getpalindromelength(string str)
// rad[i]表示以i為中心的回文的最大半徑,i至少為1,即該字元本身
int rad = new int[newstr.length()];
// right表示已知的回文中,最右的邊界的座標
int right = -1
;// id表示已知的回文中,擁有最右邊界的回文的中點座標
int id = -1
;// 2.計算所有的rad
// 這個演算法是o(n)的,因為right只會隨著裡層while的迭代而增長,不會減少。
for (int i = 0
; i < newstr.length(); i ++)
// 2.2.嘗試更大的半徑
while (i - r >= 0 && i + r < newstr.length() && newstr.charat(i - r) == newstr.charat(i + r))
// 2.3.更新邊界和回文中心座標
if (i + r - 1> right)
rad[i] = r;
} // 3.掃瞄一遍rad陣列,找出最大的半徑
int maxlength = 0
;for (int r : rad)
}return maxlength - 1
;}
求字串中最長回文串的長度
給出乙個只由小寫英文本元a,b,c y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 input 輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c y,z組成的字串s 兩組case之間由空行隔開 該空行不用處理 字串長度len 1...
求最長回文字串的長度
題目描述 輸入乙個字串,求出其中最長的回文字串的長度。子串的含義為 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。在判斷時,應該忽略所有標點符號和空格,且忽略大小寫,但輸出應保持原樣 在回文串的首部和尾部不要輸出多餘字元 輸入字串長度不超過5000,且佔據單獨...
Manacher演算法 求字串中最長回文串
manacher演算法在對求字串中最長回文串問題中,具有o n 時間和空間複雜度。演算法的精妙之處在於巧妙的利用了回文串的對偶性質。第一步 對字元間新增間隔符,例如,字串aababcdab,通過新增間隔符轉化為 a a b a b c d a b 從而避免了字串的奇偶性問題,為了避免演算法中考慮邊界...