leetcode之动态规划(三)

来源:互联网 发布:法治知识网络大赛入口 编辑:程序博客网 时间:2024/04/29 18:16

1.Interleaving String

1)题目

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.

2)分析

设状态f[i][j],表示s1[0,i]和s2[0,j],匹配s3[0,i+j]。如果s1的最后一个字符等于s3的最后一个字符,则f[i][j] = f[i-1][j];如果s2的最后一个字符等于s3的最后一个字符,则f[i][j] = f[i][j-1]。

状态方程如下:

f[i][j] = (s1[i-1] == s3[i +j -1] && f[i-1][j] )||(s2[j-1] == s3[i + j -1]&&f[i][j-1]);


3)实现

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        const int n = s1.size();        const int m = s2.size();        if(n+m!=s3.size()) return false;        vector<vector<bool>> f(n+1,vector<bool>(m+1,true));                for(int i=1;i<=n;++i) {            f[i][0] = (s1[i-1] == s3[i-1]) && f[i-1][0];        }        for(int j=1;j<=m;++j) {            f[0][j] = (s2[j-1] == s3[j-1]) && f[0][j-1];        }                for(int i=1;i<=n;++i) {            for(int j=1;j<=m;++j) {                f[i][j] = (s1[i-1]==s3[i+j-1]&&f[i-1][j]) || (s2[j-1]==s3[i+j-1]&&f[i][j-1]);            }        }        return f[n][m];    }};

2.Distinct Subsequences

1)题目

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

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.

2)分析

设状态为f[i][j],表示T[0,j]在S[0,i]出现的次数。首先,无论S[i]和T[j]是否相等,若不使用s[i],则f[i][j] = f[i-1][j];若s[i]==T[j],则可以使用S[i],此时f[i,j] = f[i-1][j] + f[i-1][j-1]。


3)实现

class Solution {public:    int numDistinct(string s, string t) {        const int n = s.size();        const int m = t.size();                vector<vector<int>> f(n+1,vector<int>(m+1,0));                for(int i=0;i<=n;i++) {            f[i][0] = 1;        }                for(int i=1;i<=n;++i) {            for(int j=1;j<=m;++j) {                if(s[i-1]!=t[j-1]) {                    f[i][j] = f[i-1][j];                } else {                    f[i][j] = f[i-1][j] + f[i-1][j-1];                }            }        }        return f[n][m];    }};


3.Edit Distance

1)题目

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

2)分析

设状态为f[i][j],表示A[0,i]和B[0,j]之间的最小编辑距离。


3)实现

class Solution {public:    int minDistance(string word1, string word2) {        const int n = word1.size();        const int m = word2.size();                vector<vector<int>> f(n+1,vector<int>(m+1,0));        for(int i=0;i<=n;++i) {            f[i][0] = i;        }        for(int j=0;j<=m;++j) {            f[0][j] = j;        }                for(int i=1;i<=n;++i) {            for(int j=1;j<=m;++j) {                if(word1[i-1] == word2[j-1]) {                    f[i][j] = f[i-1][j-1];                } else {                    int mn = min(f[i-1][j-1],f[i-1][j]);                    mn = min(mn,f[i][j-1]);                    f[i][j] = mn + 1;                }            }        }        return f[n][m];    }};

4.最长公共子序列


总结:两个字符串题型,一般用两个for循环求出所有f[n+1][m+1],求f[i][j]时,比较s1[i]和s2[j]是否相等,如果相等状态怎么转移,如果不相等,状态怎么转移。且应从空开始,所以要初始化f[i][0]和f[0][j]。并且for循环边界=n和=m。

for(int i=0;i<=n;i++) {    f[i][0] = ...;}for(int i=0;i<=n;i++) {    f[i][0] = ...;}for(int i=1;i<=n;i++) {    for(int j=1;j<=m;j++) {         f[i][j] = ...;    }}



0 0
原创粉丝点击