【LeetCode】动态规划——72.编辑距离、10.正则表达式匹配

发布于:2025-08-31 ⋅ 阅读:(26) ⋅ 点赞:(0)

LeetCode题目链接
https://leetcode.cn/problems/edit-distance/description/
https://leetcode.cn/problems/regular-expression-matching/description/

题解
72.编辑距离
本题要定义为长度为i、长度为j的字符串的最少编辑次数,每次判断字符的下标为i-1、j-1。dp[i][j]的状态由dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]共同决定,从dp[i-1][j]到dp[i][j]表示word1加上下标为i-1的字符后,与word2的距离差距,可以得知dp[i][j]=dp[i-1][j]+1;同理可得dp[i][j]=dp[i][j-1]+1,即word1加上第j-1个字符后所需的操作的个数多了个1,可以理解为删除;同理,此处需判断两个字符串的当前下标为i-1的字符和下标为j-1的字符是否相等,如果相等,就不需要增加操作个数,直接等于dp[i-1][j-1]即可,如果不相等,需要替换一次(不是删除两次,要求最小操作个数),则就等于dp[i-1][j-1]+1。由此可以的值最终dp[i][j]由上三者取最小值即可。同时对于初始化,由于第0行和第0列分别代表空字符串与word1、word1的挨个字符所需的操作次数,因此需要初始化为对应的递增值,简单点可以直接初始化为下标i、下标j的值即可。

10.正则表达式匹配
思路详见题解,c++版代码详见评论区。
需要注意的是判断*这个字符时,它与前面一个字符的组合可以被干掉,也就是可以重复0次(根据题意),因此可以往前跳两位字符再继续判断。

代码

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word2.size() + 1, vector<int>(word1.size() + 1, 0));
        for (int i = 0;i <= word2.size();i++) {
            dp[i][0] = i;
        }
        for (int j = 0;j <= word1.size();j++) {
            dp[0][j] = j;
        }
        for (int i = 1;i <= word2.size();i++) {
            for (int j = 1;j <= word1.size();j++) {
                if (word2[i - 1] == word1[j - 1]) {
                    dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j - 1]));
                }
                else {
                    dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1));
                }
            }
        }
        printf("dp[i][j]\n");
        for (int i = 0;i <= word2.size();i++) {
            for (int j = 0;j <= word1.size();j++) {
                printf("%d ", dp[i][j]);
            }
            printf("\n");
        }
        return dp[word2.size()][word1.size()];
    }
};

int main() {
    Solution s;
    string word1 = "intention";
    string word2 = "execution";
    printf("%d", s.minDistance(word1, word2));
    return 0;
}
//10.正则表达式匹配
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    bool isMatch(string s, string p) {
        if (p.empty() && !s.empty()) return false;
        //if (s.empty() && !p.empty() && p[j - 1] != '*') return false;
        vector<vector<bool>> dp(s.size() + 1, vector<bool>(p.size() + 1, false));
        dp[0][0] = true; //两个空字符串
        for (int j = 1;j <= p.size();j++) {  //s为空,但p因为* 可以干掉一个字符(即题意中的可以重复零次)
            if (p[j] == '*')
                dp[0][j + 1] = dp[0][j - 1];
        }
        

        for (int i = 1;i <= s.size();i++) {
            for (int j = 1;j <= p.size();j++) {
                if (s[i - 1] == p[j - 1] || p[j - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                else {
                    if (p[j - 1] == '*') {
                        if (s[i - 1] == p[j - 2] || p[j - 2] == '.') {
                            dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2] || dp[i - 1][j];   //重复0次、重复1次、重复2次以上
                        }
                        else {
                            dp[i][j] = dp[i][j - 2];  //不匹配,*干掉一个字符
                        }
                    }
                }
            }
        }
        return dp[s.size()][p.size()];
    }
};


int main() {
    Solution s;
    string str1 = "ab";
    string str2 = ".*";
    printf("%d", s.isMatch(str1, str2));
    return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到