給乙個字串,找出它的最長的回文子串行的長度。例如,如果給定的序列是「bbabcbcab」,則輸出應該是7,「babcbab」是在它的最長回文子串行。 「bbbbb」和「bbcbb」也都是該字串的回文子串行,但不是最長的。注意和最長回文子串的區別(參考:最長回文串)!這裡說的子串行,類似最長公共子串行lcs( longest common subsequence)問題,可以是不連續的。這就是lps(longest palindromic subsequence)問題。
最直接的解決方法是:生成給定字串的所有子串行,並找出最長的回文序列,這個方法的複雜度是指數級的。下面來分析怎麼用動態規劃解決。
假設 x[0 ... n-1] 是給定的序列,長度為n. 讓 l(0,n-1) 表示 序列 x[0 ... n-1] 的最長回文子串行的長度。
1. 如果x的最後乙個元素和第乙個元素是相同的,這時:l(0, n-1) = l(1, n-2) + 2 , 還以 「bbabcbcab」 為例,第乙個和最後乙個相同,因此 l(1,n-2) 就表示藍色的部分。
2. 如果不相同:l(0, n-1) = max ( l(1, n-1) , l(0, n-2) )。 以」babcbca」 為例,l(1,n-1)即為去掉第乙個元素的子串行,l(0, n-2)為去掉最後乙個元素。
有了上面的公式,可以很容易的寫出下面的遞迴程式:
01
#include
02
#include
03
int
lps(
char
*seq,
int
i,
int
j)
04
17
18
/* 測試 */
19
int
main()
20
output: the lnegth of the lps is 5 (即為: amama)
畫出上面程式的遞迴樹(部分),已乙個長度為6 的字串為例:
1
l(0, 5)
2
/ \
3
/ \
4
l(1,5) l(0,4)
5
/ \ / \
6
/ \ / \
7
l(2,5) l(1,4) l(1,4) l(0,3)
可見有許多重複的計算,例如l(1,4)。該問題符合動態規劃的兩個主要性質:重疊子問題
和最優子結構
。下面通過動態規劃的方法解決,通過自下而上的方式打表,儲存子問題的最優解。
01
int
lpsdp(
char
* str,
int
n)
else
16
dp[j][j+i] = tmp;
17
}
18
}
19
//返回串 str[0][n-1] 的結果
20
return
dp[0][n-1];
21
}
該演算法的時間複雜度為o(n^2)。其實這個問題和 最長公共子串行 問題有些相似之處,我們可以對lcs演算法做些修改,來解決此問題:
1) 對給定的字串逆序 儲存在另乙個陣列 rev 中
2) 再求這兩個 字串的 lcs的長度
時間複雜度也為 o(n^2)。
參考:
動態規劃 最長回文子串
動態規劃 最長回文子串 題目描述 給出乙個字串s,求s的最長回文子串的長度 樣例 字串 patzjujztaccbcc 的最長回文子串為 atzjujzta 長度為9。動態規劃思想 令dp i j 表示s i 至s j 所表示的子串是否是回文子串,是則為1,不是為0。這樣根據s i 是否等於s j ...
動態規劃 最長回文子串
給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb 本題有很多種解法,最簡單的暴力求解,但是會超時。下面分別說明動態規劃法和中心擴散法。解法一 動態規劃法...
最長回文子串 動態規劃
給出乙個字串s,求s的最長回文子串的長度。樣例輸入 patzjujztaccbcc 輸出 9 尋找二維動態規劃表示式dp i j 如果直接用dp i j 表示子符串從s i 到s j 的最長回文子串長度無法得出遞推表示式。令dp i j 表示s i 至s j 所表示的子串是否是回文子串,是則為1,不...