1. 程式人生 > >最長迴文子串求解問題方法總結

最長迴文子串求解問題方法總結

原文網址:http://blog.163.com/zhaohai_1988/blog/static/2095100852012716105847112/

 最長迴文子串是最初我在網易筆試的時候遇見的,當時天真的把原字串S倒轉過來成為S‘,以為這樣就將問題轉化成為了求S和S’的最長公共子串的問題,而這個問題是典型的DP問題,我也在前面的文章中介紹了3種解決這個問題的方法。但是非常可惜,後來才知道這個演算法是不完善的。那麼到底為什麼呢?聽我慢慢道來。

S=“c a b a”  那麼  S' = “a b a c”, 這樣的情況下 S和 S‘的最長公共子串是aba,沒有錯誤。但是當 S=“abacdfgdcaba”, 那麼S’ = “abacdgfdcaba”。 這樣S和S‘的最長公共子串是abacd。很明顯abacd並不是S的最長迴文子串,它甚至連回文都不是。

    現在是不是都明白為什麼最長迴文子串不能轉化成為最長公共子串問題了。當原串S中含有一個非迴文的串的反序串的時候,最長公共子串的解法就是不正確的。正如上一個例子中S既含有abacd,又含有abacd的反串cdaba,並且abacd又不是迴文,所以轉化成為最長公共子串的方法不能成功。除非每次我們求出一個最長公共子串的時候,我們檢查一下這個子串是不是一個迴文,如果是,那這個子串就是原串S的最長迴文子串;如果不是,那麼就去求下一個次長公共子串,以此類推。

最長迴文子串有很多方法,分別是1暴力法,2 動態規劃, 3 從中心擴充套件法,4 著名的manacher演算法。下面我將分別介紹幾種方法。

方法一 暴力法

遍歷字串S的每一個子串,去判斷這個子串是不是迴文,是迴文的話看看長度是不是比最大的長度maxlength大。遍歷每一個子串的方法要O(N2),判斷每一個子串是不是迴文的時間複雜度是O(N),所以暴利方法的總時間複雜度是O(N3)。

方法二 動態規劃 時間複雜度O(N2), 空間複雜度O(N2)

    動態規劃就是暴力法的進化版本,我們沒有必要對每一個子串都重新計算,看看它是不是迴文。我們可以記錄一些我們需要的東西,就可以在O(1)的時間判斷出該子串是不是一個迴文。這樣就比暴力法節省了O(N)的時間複雜度哦,嘿嘿,其實優化很簡單吧。

P(i,j)為1時代表字串Si到Sj是一個迴文,為0時代表字串Si到Sj不是一個迴文。

P(i,j)= P(i+1,j-1)(如果S[i] = S[j])。這是動態規劃的狀態轉移方程。

P(i,i)= 1,P(i,i+1)= if(S[i]= S[i+1])

string longestPalindromeDP(string s){

intn = s.length();

intlongestBegin =0;

intmaxLen =1;

booltable[1000][1000]={false};

for(inti =0; i < n; i++){

table[i][i]=true;//前期的初始化

}

for(inti = 0; i < n-1; i++) {

if(s[i] == s[i+1]) {

table[i][i+1] = true; //前期的初始化

longestBegin = i;

maxLen = 2;

}

}

for(intlen = 3; len <= n; len++) {

for(inti = 0; i < n-len+1; i++) {

intj = i+len-1;

if(s[i] == s[j] && table[i+1][j-1]) {

table[i][j] = true;

longestBegin = i;

maxLen = len;

}

}

}

returns.substr(longestBegin, maxLen);

}

方法三 中心擴充套件法

    這個演算法思想其實很簡單啊,時間複雜度為O(N2),空間複雜度僅為O(1)。就是對給定的字串S,分別以該字串S中的每一個字元C為中心,向兩邊擴充套件,記錄下以字元C為中心的迴文子串的長度。但是有一點需要注意的是,迴文的情況可能是 a b a,也可能是 a b b a。

string expandAroundCenter(string s,intc1,intc2){

intl = c1, r = c2;

intn = s.length();

while(l >=0&& r <= n-1&& s[l]== s[r

相關推薦

求解問題方法總結

原文網址:http://blog.163.com/zhaohai_1988/blog/static/2095100852012716105847112/  最長迴文子串是最初我在網易筆試的時候遇見的,當時天真的把原字串S倒轉過來成為S‘,以為這樣就將問題轉化成為了求S和

資料結構與演算法隨筆之------四種方法求解(暴力列舉+動態規劃+中心擴充套件+manacher演算法(馬拉車))

所謂迴文串,就是正著讀和倒著讀結果都一樣的迴文字串。 比如: a, aba, abccba都是迴文串, ab, abb, abca都不是迴文串。 一、暴力法 方法一:直接暴力列舉 求每一個子串時間複雜度O(N^2), 判斷子串是不是迴文O(N),兩者是相乘關係,所以時間

Manacher馬拉車演算法求解

        馬拉車演算法是一種能在O(n)的時間複雜度範圍內得出結果。我看了不下幾次這個演算法,每次都覺得有點懂了,但是一碰到題目了,就生生寫不出來。歸根揭底,還是沒有掌握其思想。 馬拉車演算法的第一個核心思想就是往原始的字串裡填充一些輔助的東西,使得我們在考慮問題時不

O(n)的方法長度(Manacher演算法)

大體思路其實就是找出一箇中心點,判斷中心點兩端的迴文串半徑是多少; 但由於找中心點的方法只適用於奇數長的迴文串,故可以在每兩個字元間插入一個間隔符來幫助結算; 用rd[i]表示以經過填充後的字串裡的第i個字元為中心,它的迴文串長度; 可以得知,在【

HiHo 1032 (Manacher演算法求解)

Manacher演算法o(n)求解最長迴文子串問題 非常巧妙 #include<bits/stdc++.h> using namespace std; char str[2000020],s[2000020]; int p[2000020]; int len,

leetcode5:Longest Palindromic Substring

python版: class Solution: def longestPalindrome(self, s): """ :type s: str :rtype: str """ start = en

【HDU - 3068】(Manacher演算法,馬拉車演算法求

題幹: 給出一個只由小寫英文字元a,b,c...y,z組成的字串S,求S中最長迴文串的長度.  迴文就是正反讀都是一樣的字串,如aba, abba等 Input 輸入有多組case,不超過120組,每組輸入為一行小寫英文字元a,b,c...y,z組成的字串S  兩

DP

給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: "babad" 輸出: "bab" 注意: "aba"也是一個有效答案。 示例 2: 輸入: "cbbd" 輸出: "bb" 分析:dp    dp[ j ][ i

【探索-中級演算法】

這一題可以參考:647. 迴文子串 本質上是一樣的,要判斷出所有的迴文字串,然後找到其中最長的那一個。 中心擴充套件法 中心擴充套件就是把給定的字串的每一個字母當做中心,向兩邊擴充套件,這樣來找最長的子迴文串。演算法複雜度為O(N^2) public Stri

LeetCode5

這兩天被這個題弄得是有些崩潰了,因為之前試的兩種方法都是超時了,所以弄得後面都有些不想弄了。還好有度娘,最後用的是從中間往兩邊擴充套件的方法得此解決,真的是如釋重負啊!廢話不說,講正文貼程式碼。 題目如下: 給定一個字串 s,找到 s 中最長的迴文子串。你可以假

(Longest Palindromic Substring)

題目描述: 給出一個字串(假設長度最長為1000),求出它的最長迴文子串,你可以假定只有一個滿足條件的最長迴文串。 樣例 給出字串 "abcdzdcab",它的最長迴文子串為 "cdzdc"。 挑戰 O(n2) 時間複雜度的演算法是可以接受的,如果你

演算法學習——尋找字串中的

文章轉載自公眾號《網際網路偵查》 /** * @author xiaoshi on 2018/9/24. * Happy Mid-Autumn Festival */ public class PlalindromeString { // 判斷一個字串是否迴文,演算法中用

LeetCode 5(java程式碼)

方法一:動態規劃       定義P(i,j):如果字串從i位置到j位置是迴文,P(i,j)=true;否則,P(i,j)=false;      那麼P(i,j)= P(i+1,j−1) && Si==Sj &

大連續序列和/不下降序列/公共序列/

//最大連續子序列和 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 10010; int A[maxn],dp[maxn]; int main(){ int

--演算法思想探討和實現(python java)

最長迴文子串–演算法思想探討和實現(python java) 迴文串定義: 如果一個字串正著讀和反著讀是一樣的,那它就是迴文串。 下面是一些迴文串的例項: 12321 a aba abba aaaa tattarrattat 問題定義 最長迴

leetcode5:

1 題目 給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: “babad” 輸出: “bab” 注意: "aba"也是一個有效答案。 示例 2: 輸入: “cbbd” 輸出: “bb” 題目連結: https

leetcode演算法題—golang—(題5)

題目:最長迴文子串 給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: "babad" 輸出: "bab" 注意: "aba"也是一個有效答案。 示例 2: 輸入: "cbb

LetCode: 5.

提示 LintCode中的相關演算法題實現程式碼,可以在我的GithHub中下載。 題目需求 給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: "babad" 輸出: "ba

leetcode-5-(longest palindromic substring)-java

題目及測試 package pid005; /*最長迴文子串 給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: "babad" 輸出: "bab" 注意: "aba"也是一個有效答案。 示例 2: 輸入: "cbbd" 輸出:

馬拉車演算法(求)

1 #include <vector> 2 #include <iostream> 3 #include <string> 4 5 using namespace std; 6 7 string Manacher(string s) {