夕拾演算法高階篇 16 最長回文子串 動態規劃DP

2021-07-26 12:28:12 字數 1511 閱讀 3624

給出乙個字串s,求s的最長回文子串的長度。

樣例:字串「patzjujztaccbcc」的回文子串為「atzjujzta」,長度為9。

如果使用暴力解法,列舉子串的兩個端點i和j,時間複雜度需要o(n^2)。判斷子串是否為回文需要o(n),總體時間複雜度為o(n^3),使用動態規劃可以達到最優的o(n^2),而使用動態規劃解決最長回文子串的方法有很多種,下面討論最簡單的一種方法。

令dp[i][j]表示s[i]至s[j]所表示的子串是否為回文子串,是則為1,不是為0。如此根據s[i]是否等於s[j],可以把問題分為兩類:

(1)s[i]==s[j],那麼只要s[i+1]至s[j-1]是回文子串,s[i]至s[j]就是回文子串;如果s[i+1]至s[j-1]是不是回文子串,則s[i]至s[j]也不是回文子串。

(2)s[i]!=s[j],那麼s[i]至s[j]一定不是回文子串。  

由此可以 寫出其狀態轉移方程:

邊界:dp[i][i]=1,dp[i][i+1]=(s[i]==s[i+1]?0:1)       ps:這裡的dp初始化記錄了長度為1和2的回文子串

但是這裡還存在乙個問題,就是在求dp[i][j]時,無法保證dp[i+1][j-1]已經被計算了,比如先固定i=0,然後j從2開始列舉。當求解dp[0][2]時,的dp[1][1]已經在初始中得到;當求解dp[0][3]時,會轉換求dp[1][2],而dp[1][2]也在初始化是獲得了;當求解dp[0][4]是,轉換求解dp[1][3],但dp[1][3]之前卻沒有被計算出來,因此無法轉移狀態。

根據上面的公式,邊界表示的是長度為1和2的回文子串,且每次轉移時都說對子串的長度減1。因此不妨按照子串的長度和子串的初始位置進行列舉,即第一次可以列舉長度為3的子串的dp值,第二次在第一次的基礎上列舉長度為4的子串的dp值....直到列舉到原字串的長度。長度為3的示意圖如下:

根據上面的分析,可以給出下面的**:

#include #include #include using namespace std;

const int m=1010;

int dp[m][m];

int main()

bool isdigit(char c)

char* toupper(char* v)

} return v;

}int main()

} str=toupper(str);

int len=strlen(str);

for(i=0;i=0;j--)

} }

s=pos[s]; e=pos[e];

for(i=s;i<=e;i++)

printf("\n");

}

另外關於o(n)的回文演算法manacher,可以參考:

力扣演算法篇 最長回文子串

求解len i 設 l,r 表示當前最靠右的子回文串的邊界 1 若i r,則該子回文串對len i 的計算無法起到任何幫助,直接呼叫樸素演算法計算len i 2 若i r,則說明元素s i 處於該子回文串內,由於回文串的特性,我們可以在該子回文串的左側找到乙個與s i 對稱的元素s j 那麼我們可以...

演算法 最長回文子串

題目描述 對於乙個字串,請設計乙個高效演算法,計算其中最長回文子串的長度。給定字串a以及它的長度n,請返回最長回文子串的長度。例如 輸入 abc1234321ab 12 返回值 7 最長回文子串 public static intgetlongestpalindrome string a,int n...

最長回文串 演算法 4 求解最長回文子串

問題描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。注釋 回文通俗的說就是正著念和反著念都一樣,如 上海自來水來自海上。示例 1 輸入 dabccbac 輸出 abccba 示例 2 輸入 cbbd 輸出 bb 解題思路 此處撰寫解題思路 遍歷每乙個索引,...