您的位置:首页 > 其它

使用动态规划求解字符串问题

2018-01-08 10:52 465 查看

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


问题解析:

1. 本题是求两个字符串s1和s2,编辑s1让其变为s2。可以在s1中插入字符操作、删除字符操作、替换字符操作,每次操作增加步骤1次,求s1变为s2的最小步骤数。
2. 解决此类问题经典解法就是用动态规划。
       (1)s1大小为size1,s2大小为size2。定义一个size1+1*size2+1的dp,其中dp[i][j]表示s1的前i的字符变为和s2的前j个字符所需要的最小步骤数。
       (2)dp[i][j]的值应该是:当s1[i]==s2[j]时,dp[i][j]==dp[i-1][j-1];当s[i] != s[j]时,dp[i][j] = dp[i-1][j]+1(删除一个字符)、dp[i][j] = dp[i][j-1] + 1(添加一个字符)、dp[i][j] = dp[i-1][j-1] + 1(替换一个字符)。选择三者步骤数最少的一个。

代码如下:

class Solution {
public:
// 使用动态规划来解决此问题,创建dp,dp[i][j]表示word1的i个字符转化为word2的前j个字符所需要的花费
int minDistance(string word1, string word2)
{
int m = (int)word1.size();
int n = (int)word2.size();

// 创建dp
vector<vector<int>>dp(m+1, vector<int>(n+1, 0));
// 初始化第一行,代表word1为空时转化为word2
for(int j=1; j<=n; ++j)
dp[0][j] = dp[0][j-1] + 1;
// 初始化第一列,代表word2为空时转化为word1
for(int i=1; i<=m; ++i)
dp[i][0] = dp[i-1][0] + 1;
for(int i=1; i<=m; ++i)
{
for(int j=1; j<=n; ++j)
{
// dp[i-1][j]表示word1前i-1转换为word2前j个,需要花费,删掉1个就是前i和前j
// dp[i][j-1]表示word1前i转换为word2前j-1个,需要花费,添加1个就是前i和前j
// dp[i-1][j-1]表示word1前i-1转换为word2前j-1个需要花费。word1[i]==word2[j],则不需要花费就是前i和前j.否则需要替换多花费1
int z;
dp[i][j] = dp[i-1][j] < dp[i][j-1] ? dp[i-1][j]+1 : dp[i][j-1]+1;
z = (word1[i-1] == word2[j-1] ? dp[i-1][j-1] : dp[i-1][j-1]+1);
dp[i][j] = dp[i][j] < z ? dp[i][j] : z;

}
}
return dp[m]
;
}
};

115. Distinct
Subsequences---求字符串S中有几个字符串t

问题描述:

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
.

问题解析:

1. 此题是求一个字符串S中有几个字符串t。可以转化为上题,只是通过在字符串S中删除字符来变为字符串t,看有几种解法。
2. 解决此类问题经典解法就是用动态规划。
       (1)s大小为size1,t大小为size2。定义一个size1*size2的dp,其中dp[i][j]表示s1的前i+1的字符变为和s2的前j+1个字符的方法数。
       (2)dp[i][j]的值应该是:当s1[i]==s2[j]时,dp[i][j]==dp[i-1][j] + dp[i-1][j-1],表示的是使用当前这个字符和不要s中当前这个字符总共方法数;当s[i] != s[j]时,dp[i][j] = dp[i-1][j],s中当前这个字符一定用不上,所以表示不用当前这个字符的方法数。

代码如下:

class Solution {
public:
// 利用动态规划来做
int numDistinct(string s, string t)
{
if(s.empty())
return 0;
if(t.empty())
return 1;
int ssize = s.size();
int tsize = t.size();
vector<vector<int>> dp(ssize, vector<int>(tsize, 0));
// 填写第一行
if(s[0] ==t[0])
dp[0][0]=1;
// 填写第一列
for(int i=1; i<ssize; ++i)
{
if(t[0] ==s[i])
dp[i][0] = 1+ dp[i-1][0];
else
dp[i][0] = dp[i-1][0];
}
// 填写剩余的dp
for(int i=1; i<ssize; ++i)
{
for(int j=1; j<tsize; ++j)
{
if(s[i] == t[j])
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
else
dp[i][j] = dp[i-1][j];
}
}
return dp[ssize-1][tsize-1];
}
};


115. Distinct
Subsequences
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: