双序列DP

Longest Common Subsequence 

Given two strings, find the longest common subsequence (LCS).

Your code should return the length of LCS.

Example

For "ABCD" and "EDCA", the LCS is "A" (or "D""C"), return 1.

For "ABCD" and "EACB", the LCS is "AC", return 2.


public class Solution {
    /*
     * @param A: A string
     * @param B: A string
     * @return: The length of longest common subsequence of A and B
     */
    /*
    state:dp[i][j] 代表A序列的前i个字符配上B序列的前j个字符LCS的长度
    function:if(A[i] == B[j]) dp[i][j] = dp[i-1][j-1]+1
             if(A[i] != B[j]) dp[i][j] = max(dp[i-1][j],dp[i][j-1])
    intialize:dp[i][0] = 0 dp[0][i] = 0
    answer:dp[m][n]
    */
    public int longestCommonSubsequence(String A, String B) {
        // write your code here
        if(A == null || B == null || A.length() == 0 || B.length() == 0) return 0;
        int m = A.length();
        int n = B.length();
        int[][] dp = new int[m+1][n+1];
        
        dp[0][0] = 0;
        for(int i = 1; i <= m; i++)
            dp[i][0] = 0;
        for(int j = 1; j <= n; j++)
            dp[0][j] = 0;
            
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(A.charAt(i-1) == B.charAt(j-1))
                    dp[i][j] = dp[i-1][j-1] + 1;
                else
                    dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
            }
        }
        return dp[m][n];
        
    }
}
Longest Common Substring 

Given two strings, find the longest common substring.

Return the length of it.

 Notice

The characters in substring should occur continuously in original string. This is different with subsequence.

Example

Given A = "ABCD", B = "CBCE", return 2.

public class Solution {
    /*
     * @param A: A string
     * @param B: A string
     * @return: the length of the longest common substring.
     */
     /*
    state:dp[i][j] 代表A序列的前i个字符配上B序列的前j个字符LCS的长度(一定以第i个和第j个结尾)
    function:if(A[i] == B[j]) dp[i][j] = dp[i-1][j-1]+1
             if(A[i] != B[j]) dp[i][j] = 0
    intialize:dp[i][0] = 0 dp[0][i] = 0
    answer:dp[m][n]
    */
    public int longestCommonSubstring(String A, String B) {
        // write your code here
        if(A == null || B == null || A.length() == 0 || B.length() == 0) return 0;
        int m = A.length();
        int n = B.length();
        int[][] dp = new int[m+1][n+1];
        
        dp[0][0] = 0;
        for(int i = 1; i <= m;i++)
            dp[i][0] = 0;
        for(int j = 1; j <= n; j++)
            dp[0][j] = 0;
        int maxValue = Integer.MIN_VALUE;
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(A.charAt(i-1) == B.charAt(j-1))
                    dp[i][j] = dp[i-1][j-1] + 1;
                else
                    dp[i][j] = 0;
                 maxValue = Math.max(maxValue,dp[i][j]);
            }
        }
        return maxValue;
    }
}

72. Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

/*
state:dp[i][j] 第一个序列前i个字符配上第二个序列的前j个字符至少需要几次编辑使他们相等
function:if(A[i] == B[j]) dp[i][j] = min(dp[i][j-1] + 1,dp[i-1][j] +1 dp[i-1][j-1])
         if(A[i] != B[j]) dp[i][j] = min(dp[i][j-1],dp[i-1][j],dp[i-1][j-1]) + 1
intialise:dp[i][0] = i dp[0][j] = j
answer:dp[m][n]
*/
class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m+1][n+1];
        dp[0][0] = 0;
        for(int i = 1; i <= m; i++)
            dp[i][0] = i;
        for(int j = 1; j <= n; j++)
            dp[0][j] = j;
        
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(word1.charAt(i-1) == word2.charAt(j-1))
                    dp[i][j] = Math.min(Math.min(dp[i][j-1],dp[i-1][j])+1,dp[i-1][j-1]);
                else
                    dp[i][j] = Math.min(Math.min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1])+1;
            }
        }
        return dp[m][n];
    }
}

97. Interleaving String

Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

/*
state:dp[i][j] s1前i个字符配上s2的前j个字符能否组成s3的前(i+j)个字符
function:dp[i][j] = (s1[i-1] == s3[i+j-1] && dp[i-1][j]) || (s2[j-1] == s3[i+j-1] && dp[i][j-1])
intialise:dp[i][0] = s1[i] == s3[i]; dp[0][j] = s2[j] == s3[j]; 
answer:dp[m][n]
*/
class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if(s1.length() + s2.length() != s3.length()) return false;
        int m = s1.length(),n = s2.length();
        boolean[][] dp = new boolean[m+1][n+1];
        dp[0][0] = true;
        for(int i = 1; i <= m; i++)
            dp[i][0] = (s1.charAt(i-1) == s3.charAt(i-1) && dp[i-1][0]);
        for(int j = 1; j <= n; j++)
            dp[0][j] = (s2.charAt(j-1) == s3.charAt(j-1) && dp[0][j-1]);
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                dp[i][j] = (s1.charAt(i-1) == s3.charAt(i+j-1) && dp[i-1][j]) || (s2.charAt(j-1) == s3.charAt(i+j-1) && dp[i][j-1]);
            }
        }
        return dp[m][n];
    }
}


115. Distinct Subsequences

Given a string S and a string T, count the number of distinct subsequences of S which equals T.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

Here is an example:
S = "rabbbit"T = "rabbit"

Return 3.


/*
state:dp[i][j] 第一个序列前i个字符配上第二个序列的前j个字符有所少种方案
function:if(A[i] == B[j]) dp[i][j] = dp[i-1][j](原先有的) + dp[i-1][j-1]
         if(A[i] != B[j]) dp[i][j] = dp[i-1][j]
intialise:dp[i][0] = 1(空集是所有集合的子集), dp[0][j] = 0
answer:dp[m][n]
*/
class Solution {
    public int numDistinct(String s, String t) {
        int m = s.length();
        int n = t.length();
        int[][] dp = new int[m+1][n+1];
        dp[0][0] = 1;
        for(int i = 1; i <= m; i++)
            dp[i][0] = 1;
        for(int j = 1; j <= n; j++)
            dp[0][j] = 0;
        for(int j = 1; j <= n; j++){
            for(int i = 1; i <= m; i++){
                dp[i][j] = dp[i-1][j]+(s.charAt(i-1) == t.charAt(j-1)?dp[i-1][j-1]:0);
            }
        }
        return dp[m][n];
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值