區間型動態規劃
確定狀態:
最優策略產生的最長回文子串是t
,長度m
。
情況一:回文串長度為1,即乙個字母。
情況二:回文串長度大於1,那麼必定有t[0]=t[m-1]
設t[0]
是s[i]
,t[m-1]
是s[j]
,剩下的t[1...m-2]
仍然是回文串,而且是s[i+1...j-1]
的最長回文子串。
狀態:設f[i][j]
為s[i..j]
的最長回文子串的長度。
轉移方程:
f[i][j]=max
初始條件:
乙個字母也是乙個長度為1的回文串:f[0][0]=f[1][1]=...=f[n-1][n-1]=1
如果s[i]==s[i+1]
,f[i][i+1]=2
否則f[i][i+1]=1
計算順序:
區間型動態規劃:按照j-i從小到大的順序計算
長度1:f[0][0],f[1][1]....f[n-1][n-1]
長度2:f[0][1],f[1][2]....f[n-2][n-1]
…長度n:f[0][n-1]
class
solution
//length:2
for(
int i=
0;i1;i++
)//length >2
//enumeration length
for(
int len=
3;len<=n;len++
) f[i]
[j]=math.
max(f[i+1]
[j],f[i]
[j-1])
;if(ch[i]
==ch[j]
) f[i]
[j]=math.
max(f[i]
[j],f[i+1]
[j-1]+
2);}
}return f[0]
[n-1];
}}
拓展:輸出最長回文子串
用pi
用來記錄每一步的操作,從兩側向內掃瞄。
public
intlongestpalindromesubseq
(string s)
//length:2
for(
int i=
0;i1;i++
)//length >2
//enumeration length
for(
int len=
3;len<=n;len++)}
}char
res=
newchar
[f[0
][n-1]
];int p=
0,q=f[0]
[n-1]-
1;int i=
0,j=n-1;
while
(i<=j)
if(i+
1==j)
if(pi[i]
[j]==
0) i++;if
(pi[i]
[j]==
1) j--;if
(pi[i]
[j]==2)
} system.out.
println
(string.
valueof
(res));
return f[0]
[n-1];
}
記憶化搜尋:
將遞迴每個計算過的結果儲存。
class
solution
if(i+
1==j)
compute
(i+1
,j);
compute
(i,j-1)
;compute
(i+1
,j-1);
f[i]
[j]=math.
max(f[i+1]
[j],f[i]
[j-1])
;if(ch[i]
==ch[j])}
public
intlongestpalindromesubseq
(string s)
}compute(0
,n-1);
return f[0]
[n-1];
}}
LeetCode 516 最長回文子串行
這題看了好久 本來以為和最長字串差不多用動態規劃設兩個列表來算但是沒什麼頭緒 後來去看了別人的解法 看了十幾分鐘才看懂 下面這種解法 1單位要單獨拿出來算 從2開始因為互文的子串行兩頭肯定是一樣的 如 aba acbca 假如能使 martix i j 等於從 s i 到 s j 所包含的最大子串行...
leetcode 516 最長回文子串行
給定乙個字串s,找到其中最長的回文子串行。可以假設s的最大長度為1000。示例 1 輸入 bbbab 輸出 4 乙個可能的最長回文子串行為 bbbb 示例 2 輸入 cbbd 輸出 2 乙個可能的最長回文子串行為 bb 解題思路 狀態 f i j 表示 s 的第 i 個字元到第 j 個字元組成的子串...
leetcode516 最長回文子串行
給定乙個字串s,找到其中最長的回文子串行。可以假設s的最大長度為1000。示例 1 輸入 bbbab 輸出 4 乙個可能的最長回文子串行為 bbbb 示例 2 輸入 cbbd 輸出 2 乙個可能的最長回文子串行為 bb f i j 表示 s 的第 i 個字元到第 j 個字元組成的子串中,最長的回文序...