动态规划学习二
有关字符串的子序列或者配准问题
首先考虑 动态规划
2 字符串相似度/编辑距离(edit distance)
对于序列S和T,它们之间的距离定义为:对二者进行几次以下的操作
(1)删去一个字符 (2) 插入一个字符 (3) 改变一个字符
每进行一次操作,计数增加1.
将S和T变成同一个字符串的最小计数即为他们的距离
递归解法: 超时!
int minDistance(string word1, string word2) {
if(word1 == word2) return 0;
int m = word1.size();
int n = word2.size();
if(word1 == "")
{
return n;
}
if(word2 == "")
{
return m;
}
if(word1[0] == word2[0])
{
return minDistance(word1.substr(1), word2.substr(1));
}
else
{
return min(1 + minDistance(word1, word2.substr(1)), min(1 + minDistance(word1.substr(1), word2), 1 + minDistance(word1.substr(1), word2.substr(1))));
}
}
动态规划解法:
-
dp[i][j]
表示将 word1[0…j-1]变成word2[0…i-1]所需要的最少变化次数 -
每次更新时,比较 word[j-1] 与 word2[i-1]
若二者相同,则做小距离为
dp[i-1][j-1]
.若不相等,则需要 求出
dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]
三者中的最小值, 加1 即可.
class Solution {
public:
int minDistance(string word1, string word2) {
// 找到改变最少的次数将word1变成word2
int n1 = word1.size();
int n2 = word2.size();
if (n1 == 0) {
return n2;
}
if (n2 == 0) {
return n1;
}
// dp[i][j] 表示将 word1[0...j-1]变成word2[0..i-1]最少需要变化次数
vector<vector<int>> dp(n2 + 1, vector<int>(n1 + 1, INT_MAX));
dp[0][0] = 0;
// 第一行,word2为空,那么删除对应长度
for (int i = 1; i < n1 + 1; i++) {
dp[0][i] = i;
}
// 第一列,word1为空,那么需要增加对应的长度
for (int i = 1; i < n2 + 1; i++) {
dp[i][0] = i;
}
for (int i = 1; i < n2 + 1; i++) {
for (int j = 1; j < n1 + 1; j++) {
if (word1[j-1] == word2[i-1]) {
// 最后一个字符相等
dp[i][j] = dp[i - 1][j - 1];
}
else {
// 最后一个字符不等
int t= min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;
dp[i][j] = t;
}
}
}
return dp[n2 ][n1 ];
}
};
2.1 子串匹配
LeetCode 647. Palindromic Substrings
找出一个字符串中的所有回文字符串的个数.
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
}
vector<vector<bool>> dp(n , vector<bool>(n, false));
// dp[j][i]表示 是否[i..j]的是回文串
for (int j = 0; j < n; j++) {
for (int i = 0; i <= j; i++) {
// 递归公式
dp[j][i] = s[i] == s[j] && ((j - i) < 2 || dp[j - 1][i + 1]);
}
}
int sum = 0;
for (int j = 0; j < n; j++) {
for (int i = 0; i <= j; i++) {
sum += dp[j][i];
}
}
return sum;
}
};