FTPrep, 115 Distinct Subsequences, 2D DP 大总结,值得一看

好题!2D DP问题,两个字符串的比较都逃不出这个套路啊~ 啊哈哈

同类题型: 

edit distance, 两个子串的相互比较

interleaving string,两个子串合并成一个串。两个subsequence的合并问题。

distinct subsequence,两个子串的包含关系,也可以堪称是interleaving string的变体,因为短串是长串的一部分,剩下都可以认为是第二个子串。

2D DP 类型,t短s长,以t定array size, A[i+1] 记录的是 index =i 的t中字母的情况。同时进行s.length() 次迭代。A的话要从后往前,base是 A[i+1]= A[i+1], bonus是 t.i == s.j 时,还有额外的A[i]

class Solution {
    public int numDistinct(String s, String t) {
        if(t.length()==0) return 1; // t is shorter
        if(s.length()==0) return 0;  // s is longer
        int[] res = new int[t.length()+1]; // t 是target 
        res[0] = 1;  
        for(int i=0;i<s.length();i++){   // 要对s的每一个字母都进行检查。
            for(int j=t.length()-1;j>=0;j--){  // !!!从t的后面开始,j是index,代表string中字母实际的index
                //实际上是被记录在res[j+1]中,这也是为什么res的长度多1
                //在res[0]的位置,其实就是 dp 转换方程开始时 所需要的 initial value
                res[j+1] = (s.charAt(i)==t.charAt(j)?res[j]:0)+res[j+1]; // 基本保证:上一次对比时都次数肯定都在这一次的比较之后,所指至少是上一次的次数。bonus,在这某一个位置t s的字母相等了,那么就可以用t的前 (j-1)的子串 加上现在这个位置 j的字母合并成的subsequence 进行匹配,那么次数就是 (j-1)代表的字符串的次数,那就是 res[j]
            }
        }  
        return res[t.length()];  
    }
}

interleaving string

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int len1=s1.length();
        int len2=s2.length();
        if(len1+len2!=s3.length()) return false;
        String shortStr=len1<len2?s1:s2;
        String longStr=len1<len2?s2:s1;
        int shortLen = shortStr.length();
        int longLen = longStr.length();
        
        boolean[] record = new boolean[1+shortLen];
        record[0]=true;
        for(int i=0; i<shortLen; i++){  // i is the index in the shortStr, the result is in record[i+1] though
            record[i+1] = record[i]&&(shortStr.charAt(i)==s3.charAt(i));
        }
        
        for(int j=0; j<longLen; j++){  // j is also the index in the longStr.
            record[0] = record[0] && (longStr.charAt(j)==s3.charAt(j));
            for(int i=0; i<shortLen; i++){
                record[i+1] = (record[i+1]&&(longStr.charAt(j)==s3.charAt(i+j+1))) || (record[i] && (shortStr.charAt(i)==s3.charAt(i+j+1)));
            } // when i and j are index in shortStr and longStr, it is i+j+1 in the s3, since it is the length directly matches, not index
        }
        return record[shortLen];
    }
}

edit distance

class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        if(len1==0) return len2;
        if(len2==0) return len1;
        String shortWord = len1<len2?word1:word2;
        String longWord = len1<len2?word2:word1;
        int[] record = new int[shortWord.length()+1];
        for(int i=0; i<shortWord.length()+1; i++) record[i]=i;
        for(int j=0; j<longWord.length(); j++){
            int[] newRecord = new int[shortWord.length()+1];
            newRecord[0] = j+1; // the first elem present that the (j+1)th char in the longWord
            for(int i=0; i<shortWord.length(); i++){
                // newRecord[i] keep the distance between shortWord[i-1] and longWord[j], this is the difference!!
                // following the above comment, to get record[i+1], we need to compare shortWord[i] and longWord[j];
                if(shortWord.charAt(i)==longWord.charAt(j)) newRecord[i+1]=record[i]; 
                else{
                    newRecord[i+1]=Math.min(newRecord[i], Math.min(record[i], record[i+1]))+1;
                }
            }
            record=newRecord;
        }
        return record[shortWord.length()];
    }
}
// 这题和一般的DP,2D-DP的关键区别是在for loop里面同时有2个array,这是必要的,因为需要斜对角,左上方向的字母所带有的信息来判断!!在总结的时候一定要记录!!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值