動態規劃:給出兩個字符串s1和s2,返回其中最大的公共子串

求公共子字符串問題(連續的)

這個題目是當時遠景能源公司現場筆試的一道題目,當時根本就不知道動態規劃是什麼鬼,直接上來就暴力求解,面試官很諂媚的問我,你這能求出來嗎?當時很年輕的說,能啊!如今想,當時哪來的自信和逗比勇氣說這大話。。。在《進軍硅谷》這本書上看到原題,我是懵逼,怎麼想出這種解答出來的,下面直接上思路和代碼。面試

思路:

定義二維數組dp[i][j]記錄最大公共子串的長度,算法

  • 若要返回字符串能夠用s1.substring(i-dp[i][j]+1, i+1)
  • 當s[i]==s[j]時,dp[i][j]=dp[i-1][j-1]+1;
  • 當s[i]!=s[j]時,dp[i][j]=0;

有點相似於數學概括法數組

方案:

  • 首先考慮空或者長度爲0的狀況,直接返回"";
  • 而後進入雙重循環:
  • 1.利用charAt(int index)方法來比較兩個字符串相等的時機
  • 2.考慮邊界狀況,兩個字符串中有一個是起始爲0就相等,則dp[i][j]=1
  • 3.除了邊界狀況,其餘最大字符串長度爲dp[i][j]=dp[i-1][j-1]+1;
  • 4.不斷的替換掉最大的長度並返回公共子串
  • 最後循環結束後,返回最大的公共子串
 1     public static String maxCommonString(String s1, String s2) {
 2         String res = "";
 3         if (s1 == null || s1.length() == 0 || s2 == null || s2.length() == 0)
 4             return res;
 5         int max = 0, m = s1.length(), n = s2.length();
 6         int[][] dp = new int[m][n]; // 定義一個二維數組記錄最大公共子串的長度
 7         // 計算到s1的第i個字符和s2的第j個字符爲止的最大公共子串長度
 8         for (int i = 0; i < m; i++) {
 9             for (int j = 0; j < n; j++) {
10                 // 若是s1字符串在i處和s2字符串在j處有字符相同,進入if代碼塊中
11                 if (s1.charAt(i) == s2.charAt(j)) {
12                     if (i == 0 || j == 0)
13                         dp[i][j] = 1;// 邊界的狀況
14                     else
15                         dp[i][j] = dp[i - 1][j - 1] + 1;// 加上當前長度
16                     // 記錄最大長度和子串
17                     if (dp[i][j] > max) {
18                         max = dp[i][j];
19                         res = s1.substring(i - dp[i][j] + 1, i + 1);// substring()左閉右開
20                     }
21                 }
22             }
23         }
24         return res;
25     }

動態規劃介紹markdown

動態規劃算法通常是基於一個遞推公式(如上面的當s[i]==s[j]時,dp[i][j]=dp[i-1][j-1]+1;)以及一個或多個初始狀態(當s[i]!=s[j]時,dp[i][j]=0;),當前子問題實際上是由上一次子問題的解推算出來的。
【附帶福利:markdown每行縮進的方式】spa

半方的空白&ensp;或&#8194;
全方的空白&emsp;或&#8195;
不斷行的空白格&nbsp;或&#160;
(分號都是英文格式的)code

相關文章
相關標籤/搜索