動態規劃1.求最長迴文子串
阿新 • • 發佈:2018-12-28
求字串的子串大致有四中方法,暴力,DP,中心拓展,馬拉車演算法,這篇講DP怎麼做。
DP最重要的就是要能利用到前面的結果來推斷當前狀態,比暴力優化的地方就在此,暴力需要對每一個字串做一次O(n)的操作才能判斷出結果,也就是整個過程要O(n^3),但DP對每一個字串的判斷時間是O(1),總共是O(n^2)
假設s=adcdf,我們可以的推導過程就像下圖(i代表行,表示結尾,表示字串結尾,j代表列,表示字串開頭)
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
1 | a | ||||
2 | ad | d | |||
3 | adc | dc | c | ||
4 | adcd | dcd | cd | d | |
5 | adcdf | dcdf | cdf | df | f |
我們用dp[][]來表示所有可能子串是否迴文,比如dp[1][2]表示第ad,不迴文,所以dp[1][2]=false,根據上面表格可以總結一下
1.當i=j時,dp[j][i]=true
2.i-j=1時,比如dp[1][2]為ad,表示兩個相鄰的字元,此時我們只要判斷str[1]==str[2]就能得出dp[1][2]的結果
3.i-j>1時,我們來看dp[j]ij],首先還是要判斷開頭和結尾是否相等,也就是判斷
str[i]==str[j],假如此時str[i]=str[j],我們還要再看剩下的子串是否迴文,
我們可以直接從dp[j+1][i-1]來判斷剩下的子串,把結果直接拿來用
dp[j][i]=(str[i]==str[j]) ;i-j<=1
dp[j][i]=(str[i]==str[j])&&dp[j+1][i-1];i-j>1
class Solution { public String longestPalindrome(String s) { if(s.isEmpty()==true) return ""; int Len=s.length(); if(Len==1) return s; Boolean[][] dp=new Boolean[Len][Len]; int len=0,max=0,start=0,end=0; for(int i=0;i<Len;i++) { for(int j=0;j<=i;j++) { if(i-j>1) { dp[j][i]=((s.charAt(i)==s.charAt(j))&&dp[j+1][i-1]); }else { dp[j][i]=(s.charAt(i)==s.charAt(j)); } len=i-j; if(dp[j][i]==true&&len>=max) { max=len; start=j; end=i; } } } if(start==end) { String str=""; return str+s.charAt(0); } return s.substring(start, end+1); } }
題目連結:點這裡