タイトルの説明
与えられた文字列sから、sで最も長い回文の部分文字列を見つけます。sの最大長は1000と想定できます。
例1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
例2:
输入: "cbbd"
输出: "bb"
問題解決のアイデア:
DPがどのようにDPであり、何が必要かを設定します。
最初に、1次元配列dpについて考えました。dp[i]は、最初のi文字の最長のパリンドロームサブストリングを表し、注意这里的子串不是必须连续的
fは1次元を見つけました判断できません。
少なくとも2つのポインターが必要で、次に2次元に変換されます。dp[i][j] 表示i~j位置的最长回文子串
または、最後から開始して、最後の文字を含む最長の回文部分文字列を判断し、dp [i] [s.length-1]の最大値がそもそも判断すると。
1. s [0] = s [length-1]が等しくない場合、最後の文字で終わる最長の部分文字列は不包含这两者中的至少一个
3つの場合があります。
1.最後のものは含めますが、最初のものは含めません
。2.最後のものを除外し、最初のものを含め
ます。3.
図に示すように、どちらも含めないでください。
両方を同時に含めないでください。それを状態遷移方程式に追加すると、実際に追加でき、正しい答えを得ることができますが、dp [i + 1] [j-1]は小于等于
dp [i] [j -1]、dp [i + 1] [j]、maxを取得することは不可能です。iとjの間の間隔が大きいほど、同じ回文が含まれる可能性があります。逆に、値が小さいほど、それが少ないほど、紙に描くとはっきりわかる、私は怠惰で描かないよ
2. s [0] = s [length-1]が等しい場合、
dp [i] [j] = dp [i + 1] [j-1] +2、最初と最後を追加します
上記の分析から、dp [i] [j]は図に示す3つの方法で取得されていることがわかります。そのため、トラバースするときに
、境界を決定するポイントがもう1つありますdp [i] [i] = 1 ;
コードをアップロード
class Solution {
public int longestPalindromeSubseq(String s) {
int length=s.length();
int dp[][]=new int [length+1][length+1];
for(int i=length-1;i>=0;i--){
dp[i][i]=1;
for(int j=i+1;j<length;j++){
if(s.charAt(i)==s.charAt(j)){
dp[i][j]=dp[i+1][j-1]+2;
}
else{
dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]);
}
}
}
return dp[0][length-1];
}
}
この質問は最初は考えていませんでしたが、他の人の解決策を読んだ後でわかりました。理解を深めるためにこの解決策を書きました。書くのは少し面倒で、上司に手放すように頼みました。