首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法细节系列(14):动态规划之字符串处理

算法细节系列(14):动态规划之字符串处理

作者头像
用户1147447
发布2019-05-26 19:36:28
3980
发布2019-05-26 19:36:28
举报

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1435861

算法细节系列(14):动态规划之字符串处理

详细代码可以fork下Github上leetcode项目,不定期更新。

题目均摘自leetcode:

392.Is Subsequence

水题,不一定要使用DP,但既然此章节关于DP,咱们就用DP解。

    public boolean isSubsequence(String s, String t){

        if (s.isEmpty()) return true;
        int n = s.length();
        boolean[] isSeq = new boolean[n];

        int index = 0;
        for (int i = 0; i < t.length(); i++){
            if (s.charAt(index) == t.charAt(i)){
                isSeq[index++] = true;
                if (isSeq[n-1]) return true;
            }
        }
        return isSeq[n-1];
    }

516. Longest Palindromic Subsequence

一道区间DP,更新没什么好说的,但需要注意两个for循环的遍历顺序。递推式:

//dp[j][i] 表示在区间[j,i]之间的最长回文,可断
s[j] == s[i]: dp[j][i] = dp[j+1][i-1] + 2;
//没有最新的回文生成,所以沿用旧的回文长度
s[j] != s[i]: dp[j][i] = Math.max(dp[j+1][i],dp[j][i-1]);
public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];
        char[] c = s.toCharArray();
        for (int i = 0; i < n; i++) {
            dp[i][i] = 1;
            for (int j = i-1; j >= 0; j--) {
                if (c[j] == c[i]) {
                    dp[j][i] = dp[j + 1][i - 1] + 2;
                } else {
                    dp[j][i] = Math.max(dp[j+1][i], dp[j][i-1]);
                }
            }
        }
        return dp[0][n-1];
    }

72. Edit Distance

比较抽象的一道题,要求两个字符串的最短编辑距离。

dp[i][j] : 表示word1[0,i)和word2[0,j)的最短编辑距离
如:
dp[1][0] = 1, "a"," "
dp[1][1] = ?, "a","a" 相等,? = 0,"a","b" 不相等, ? = 1

初始化:(字符串为空串的情况下,最短编辑距离等于字符串长度)
dp[i][0] = i;
dp[0][j] = j;

递推式:
dp[i][j] = dp[i-1][j-1];  if word1[i] == word2[j];
dp[i][j] = min(dp[i-1][j] + dp[i][j-1] + dp[i-1][j-1]) + 1; if word1[i] != word2[j];

举个简单的例子说明它们的含义:(word1不去操作,所有操作在word2上进行)
word1 : "a"
word2 : "ab"
dp[0][0] = 0; " " == " "
dp[0][1] = 1; edit -> "&a", "&b"
dp[0][2] = 2; edit -> "&&a", "&&"
dp[1][1] = dp[0][0] = 0; "a" == "a", no edit
dp[1][2] = ?; "a" != "b"
存在三种情况:
a. dp[1][2] = dp[0][1] = 2; "&a","&b" edit -> "&a","&a"
我们已知道了dp[0][1]表示为"&a","&b",所以只能进行替换操作。
即:dp[i][j] = dp[i-1][j-1]
dp[i-1][j-1]表示了最短编辑距离,也可以表示成两字符串经过编辑后已然相等,而此时为了能够更新到dp[i][j],只能对word2的第j个字符做替换操作。

b. dp[1][2] = dp[1][1] = 1; "a","ab" edit -> "a","a"
即:dp[i][j] = dp[i][j-1]
显然,dp[1][1] = 0,没有操作。而此时为了能够更新到dp[i][j],让两字符串相等,只能删除word2的第j个字符。

c. dp[1][2] = dp[0][2] = 3; "&&a","&&" edit -> "&&a","&&a"
即:dp[i][j] = dp[i-1][j];
同理,dp[0][2] = 2, 说明了word2 = "&&",而为了能够更新到dp[i][j],只能添加到第j个字符后。

最后在这三种操作中,取最小的即可。

注意:”&”空字符串占位符,所以有”&&” = “&”,且我们所有操作只针对一个对象。代码如下:

    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();

        int[][] cost = new int[m + 1][n + 1];
        for (int i = 0; i <= m; i++)
            cost[i][0] = i;
        for (int i = 1; i <= n; i++)
            cost[0][i] = i;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (word1.charAt(i) == word2.charAt(j))
                    cost[i + 1][j + 1] = cost[i][j];
                else {
                    int a = cost[i][j];
                    int b = cost[i][j + 1];
                    int c = cost[i + 1][j];
                    cost[i + 1][j + 1] = a < b ? (a < c ? a : c) : (b < c ? b : c);
                    cost[i + 1][j + 1]++;
                }
            }
        }
        return cost[m][n];
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年05月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 算法细节系列(14):动态规划之字符串处理
    • 392.Is Subsequence
      • 516. Longest Palindromic Subsequence
        • 72. Edit Distance
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档