1. 程式人生 > >Leetcode 727. Minimum Window Subsequence

Leetcode 727. Minimum Window Subsequence

Problem:

Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of W.

If there is no such window in S that covers all characters in T, return the empty string "". If there are multiple such minimum-length windows, return the one with the left-most starting index.

Example 1:

Input: 
S = "abcdebdde", T = "bde"
Output: "bcde"
Explanation: 
"bcde" is the answer because it occurs before "bdde" which has the same length.
"deb" is not a smaller window because the elements of T in the window must occur in order.

 

Note:

  • All the strings in the input will only contain lowercase letters.
  • The length of S will be in the range [1, 20000].
  • The length of T will be in the range [1, 100].

Solution:

  這道題拿到手的第一想法應該是動態規劃,用dp[i][j]代表前i個T中的字元和前j個S中的字元在S中滿足條件的最大開始位置,說起來很繞,以Example 1為例,首先初始化第一行,當碰T[i]等於S[j]時,將j賦值給dp[i][j],否則dp[i][j]等於dp[i][j-1]。對於其餘的行,如果T[i]等於S[j],那麼dp[i][j]等於dp[i-1][j],為什麼要這麼做?那是因為我知道了前i-1個T字串和前j個S字串在S中的最大開始位置,而T[i]和S[j]又是相等的,那麼即使多了一個T中的i位置的字元也不會影響結果,所以dp[i][j]=dp[i-1][j],如果T[i]和S[j]不等,那麼dp[i][j]等於dp[i][j-1]。但這裡有個陷阱,看"cnhczmccqouqadqtmjjzl"和"mm"這個例子,如果簡單的按照這個邏輯,T的第二個m會和S的第一個m重複使用,因此需要多一布判斷T[i]和T[i-1]是否相同,如果相同的話dp[i][j]就等於dp[i-1][j-1].

  a b c d e b d d e
b -1 1 1 1 1 5 5 5 5
d -1 -1 -1 1 1 1 5 5 5
e -1 -1 -1 -1 1 1 1 1 5

 

Code:

 

 1 class Solution {
 2 public:
 3     string minWindow(string S, string T) {
 4         int m = S.size();
 5         int n = T.size();
 6         vector<vector<int>> dp(n,vector<int>(m,-1));
 7         for(int j = 0;j != m;++j){
 8             if(T[0] == S[j])
 9                 dp[0][j] = j;
10             else{
11                 if(j != 0)
12                     dp[0][j] = dp[0][j-1];
13             }
14         }
15         for(int i = 1;i != n;++i){
16             for(int j = 0;j != m;++j){
17                 if(S[j] == T[i]){
18                     if(T[i] == T[i-1]){
19                         if(j != 0)
20                             dp[i][j] = dp[i-1][j-1];
21                     }
22                     else
23                         dp[i][j] = dp[i-1][j];
24                 }
25                 else{
26                     if(j != 0)
27                         dp[i][j] = dp[i][j-1];
28                 }
29             }
30         }
31         string result = "";
32         int minlength = INT_MAX;
33         for(int j = 0;j != m;++j){
34             if(dp[n-1][j] != -1 && j-dp[n-1][j]+1 < minlength){
35                 minlength = j-dp[n-1][j]+1;
36                 result = S.substr(dp[n-1][j],minlength);
37             }
38         }
39         return result;
40     }
41 };