先要搞明白:最長公共子串和最長公共子序列的區別。java
最長公共子串(Longest Common Substirng):連續ui
最長公共子序列(Longest Common Subsequence,LCS):沒必要連續code
題目:給定一個字符串s,你能夠從中刪除一些字符,使得剩下的串是一個迴文串。如何刪除才能使得迴文串最長呢?
輸出須要刪除的字符個數。字符串
思路是:反序這個字符串,求這個新串和原串的最大子序列。abcda--->adcba 最大子序列是aca,再相減就是最少的字符刪除個數。因此問題變成了求兩個字符串的最長子序列。get
那麼怎麼求兩個字符串的最長子序列呢?既然是用動態規劃,最重要的是肯定狀態和狀態轉移方程。io
狀態:當str1的下標爲m,str2的下標是n的時候(不考慮後面的),此時的最長子序列長度L。class
轉移方程:1,若是str1(m)==str2(n),那麼L(m,n)=L(m-1,n-1)+1。2,若是str1(m)!=str2(n),那麼L(m,n)=max(L(m-1,n),L(m,n-1))。next
解釋一下,假如m和n相等,那麼這個時候最長子序列無疑是前一個L(m-1,n-1)加上1,由於這兩個字符串這個地方的字符均可以加入到最長子序列裏面去。若是不相等,那麼要麼捨棄新來的來自str1的那個字符m號,要麼捨棄str2的n號字符(最長子序列每一個位置上固然都是惟一肯定的一個字符),捨棄以後呢,就從static
L(m-1,n),L(m,n-1)當中挑一個好的(能更長的)爲當前狀態的最長子序列。動態規劃
代碼:
public class Main { public static void main(String[] args){ Solution s = new Solution(); Scanner sc = new Scanner(System.in); while(sc.hasNextLine()) { System.out.println( s.getResult(sc.nextLine()) ); } sc.close(); } } class Solution { public int getResult(String s) { StringBuilder s1 = new StringBuilder(s); StringBuilder s2 = new StringBuilder(s).reverse(); return s.length() - LCS(s1, s2); } public int LCS(StringBuilder s1, StringBuilder s2) { int m = s1.length(); int n = s2.length(); int[][] mutrix = new int[m + 1][n + 1]; for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(s1.charAt(i - 1) == s2.charAt(j - 1)) mutrix[i][j] = mutrix[i - 1][j - 1] + 1; else mutrix[i][j] = Math.max(mutrix[i - 1][j], mutrix[i][j - 1]); } } return mutrix[m][n]; } }