zoukankan      html  css  js  c++  java
  • 727. Minimum Window Subsequence

    问题描述:

    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].

    解题思路:

    仔细读题,注意这里说的是:子序列!!!

    子序列意味着每个字符之间的相对顺序不能够改变。

    解法参考了zestypanda的解法。

    是用动态规划来进行解答。

    首先搞清楚dp[j][i]的含义: 对于目标字符串T下标为[0,j]的子串作为子序列出现在给定字符串S[0, i]中的起始位置

    初始化dp[0][i]:当S[i] == T[0]时,dp[0][i] = i, else dp[0][i] = -1;

    从T的第二个字符开始遍历。

    我们用k记录对于T[0, j-1]在当前S[i]之前出现的下标。

    当dp[j-1][i] != -1的时候表示到当前i,出现了T[0,j-1]的子序列。将其存入k

    若S[i] == T[j], 且 k != -1,表示对于T[0, j]作为子序列出现了。更新dp[j][i].

    现在dp中存储的是起始位置。但是我们想要知道的是长度最小的子串。

    所以我们遍历dp[n-1][i] (因为要包含T作为子串),找到起始坐标start,子串长度i-start+1最小。

    最后需要判断子串是否存在:

    若start = -1,则不存在。

    此时的空间复杂度为O(mn),可以通过滚动数组的方式,将其优化至O(m)

    代码:

    class Solution {
    public:
        string minWindow(string S, string T) {
            int m = S.size(), n = T.size();
            vector<vector<int>> dp(n, vector<int>(m, -1));
            for(int i = 0; i < m; i++){
                if(S[i] == T[0]) dp[0][i] = i;
            }
            
            for(int j = 1; j < n; j++){
                int k = -1;
                for(int i = 0; i < m; i++){
                    if(k != -1 && S[i] == T[j]) dp[j][i] = k;
                    if(dp[j-1][i] != -1) k = dp[j-1][i];
                }
            }
            
            int start = -1, len = INT_MAX;
            for(int i = 0; i < m; i++){
                if(dp[n-1][i] != -1 && i - dp[n-1][i]+1 < len){
                    start = dp[n-1][i];
                    len = i - dp[n-1][i]+1;
                }
            }
            return start == -1 ? "":S.substr(start, len);
        }
    };
  • 相关阅读:
    POJ 3356 水LCS
    POJ 2250 (LCS,经典输出LCS序列 dfs)
    POJ 1080( LCS变形)
    整数划分问题之最大乘积
    进程调度之FCFS算法(先来先运行算法)
    c模拟银行家资源分配算法
    c模拟内存分配算法(首次适应算法,最佳适应算法,最坏适应算法)
    HDU 2602 Bone Collector(经典01背包问题)
    NYOJ 44 字串和 (最大字串和 线性dp)
    匈牙利游戏(codevs 1269)
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9344791.html
Copyright © 2011-2022 走看看