zoukankan      html  css  js  c++  java
  • 583. Delete Operation for Two Strings

    Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same, where in each step you can delete one character in either string.

    Example 1:

    Input: "sea", "eat"
    Output: 2
    Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
    

     Note:

    1. The length of given words won't exceed 500.
    2. Characters in given words can only be lower-case letters.

    题目含义:给定两个字符串,每次可以删除一个字母,求使得两个字符串相等的最小步骤

    方法一:找到最终公共子串,然后计算其余字符长度

        private String findMaxCommonSubString(String word1,String word2)
        {
            String min = word1.length()<word2.length()?word1:word2;
            String max = min.equals(word1)?word2:word1;
            if (max.contains(min)) return min;
    
            for (int i=0;i<min.length();i++)
            {
                for (int a=0,b=min.length()-i;b!=min.length()+1;a++,b++)
                {
                    String subStr = min.substring(a,b);
                    if (max.contains(subStr)) return subStr;
                }
            }
            return "";
        }
    
        public int minDistance(String word1, String word2) {
            String maxCommonSubStr = findMaxCommonSubString(word1, word2);
            if (maxCommonSubStr.isEmpty()) return word1.length() + word2.length();
            int commonPosi1 = word1.indexOf(maxCommonSubStr);
            int commonPosi2 = word2.indexOf(maxCommonSubStr);
            return word1.length() - maxCommonSubStr.length() + word2.length() - maxCommonSubStr.length();           
                return word1.length() - val + word2.length() - val;
        }

    方法二:问题可以转化为求两个字符串的最长公共子序列(注意不是子字符串,而是子序列长度)

    给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence)。比如字符串1:BDCABA;字符串2:ABCBDAB

    则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA

    这是一个动态规划的题目。对于可用动态规划求解的问题,一般有两个特征:①最优子结构;②重叠子问题

    ①最优子结构

    设 X=(x1,x2,.....xn) 和 Y={y1,y2,.....ym} 是两个序列,将 X 和 Y 的最长公共子序列记为LCS(X,Y)

    找出LCS(X,Y)就是一个最优化问题。因为,我们需要找到X 和 Y中最长的那个公共子序列。而要找X 和 Y的LCS,首先考虑X的最后一个元素和Y的最后一个元素。

    1)如果 xn=ym,即X的最后一个元素与Y的最后一个元素相同,这说明该元素一定位于公共子序列中。因此,现在只需要找:LCS(Xn-1,Ym-1)

    LCS(Xn-1,Ym-1)就是原问题的一个子问题。为什么叫子问题?因为它的规模比原问题小。(小一个元素也是小嘛....)

    为什么是最优的子问题?因为我们要找的是Xn-1 和 Ym-1 的最长公共子序列啊。。。最长的!!!换句话说,就是最优的那个。(这里的最优就是最长的意思)

    2)如果xn != ym,这下要麻烦一点,因为它产生了两个子问题:LCS(Xn-1,Ym) 和 LCS(Xn,Ym-1)

    因为序列X 和 序列Y 的最后一个元素不相等嘛,那说明最后一个元素不可能是最长公共子序列中的元素嘛。(都不相等了,怎么公共嘛)。

    LCS(Xn-1,Ym)表示:最长公共序列可以在(x1,x2,....x(n-1)) 和 (y1,y2,...yn)中找。

    LCS(Xn,Ym-1)表示:最长公共序列可以在(x1,x2,....xn) 和 (y1,y2,...y(n-1))中找。

    求解上面两个子问题,得到的公共子序列谁最长,那谁就是 LCS(X,Y)。用数学表示就是:

    LCS=max{LCS(Xn-1,Ym),LCS(Xn,Ym-1)}

    由于条件 1)  和  2)  考虑到了所有可能的情况。因此,我们成功地把原问题 转化 成了 三个规模更小的子问题。

     ②重叠子问题

    重叠子问题是啥?就是说原问题 转化 成子问题后,  子问题中有相同的问题。咦?我怎么没有发现上面的三个子问题中有相同的啊????

    OK,来看看,原问题是:LCS(X,Y)。子问题有 ❶LCS(Xn-1,Ym-1)    ❷LCS(Xn-1,Ym)    ❸LCS(Xn,Ym-1)

    初一看,这三个子问题是不重叠的。可本质上它们是重叠的,因为它们只重叠了一大部分。举例:

    第二个子问题:LCS(Xn-1,Ym) 就包含了:问题❶LCS(Xn-1,Ym-1),为什么?

    因为,当Xn-1 和 Ym 的最后一个元素不相同时,我们又需要将LCS(Xn-1,Ym)进行分解:分解成:LCS(Xn-1,Ym-1) 和 LCS(Xn-2,Ym)

    也就是说:在子问题的继续分解中,有些问题是重叠的。

    说了这么多,还是要写下最长公共子序列的递归式才完整。借用网友的一张图吧:)

    c[i,j]表示:(x1,x2....xi) 和 (y1,y2...yj) 的最长公共子序列的长度。(是长度哦,就是一个整数嘛)

        public int findLCS(String str1, String str2) {
            int n = str1.length();
            int m = str2.length();
            int[][] dp = new int[n + 1][m + 1];
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= m; j++) dp[i][j] = 0; //长度为0的串当然应该为0
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1] + 1; //i和j位置上的值相同,就在i-1和j-1的基础上+1
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]);//取(i-1,j) (i,j-1)中较大的
                    }
                }
            }
            return dp[n][m];
        }
  • 相关阅读:
    树链剖分总结
    主席树总结
    BZOJ1053:反素数(数学)
    CH3101 阶乘分解
    2018-2019 ACM-ICPC ECfinal I. Misunderstood … Missing
    洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)
    Codeforces Round #552 (Div. 3) 题解
    线段树合并 总结
    生成器
    Python中input()和raw_input()的区别
  • 原文地址:https://www.cnblogs.com/wzj4858/p/7686936.html
Copyright © 2011-2022 走看看