数据结构和算法分析程序员动态规划

lintcode 交叉字符串

2016-12-18  本文已影响413人  yzawyx0220

给出三个字符串:s1、s2、s3,判断s3是否由s1和s2交叉构成。
样例
比如 s1 = "aabcc" s2 = "dbbca"
当 s3 = "aadbbcbcac",返回 true.
当 s3 = "aadbbbaccc", 返回 false.

很多人看到这个题的第一反应是用指针,依次遍历三个字符串,但是那样无法解决选择的问题,比如s1和s2都有相同的一个字母可以和s3匹配,但是由于顺序问题可能就会导致得出错误的结果。

这种类似的字符串问题可以使用动态规划的方法,建立一个二维数组dp,dp[i][j]表示s3可以由s1的前i个和s2的前j个组成,那么子问题就是dp[i-1][j]或者dp[i][j-1],只有子问题成立(true),该问题才会成立。而dp[i-1][j]的子问题是dp[i-2][j]或者dp[i-1][j-1],以此类推,最后都会归结为判断dp[1][0]或者dp[0][1]。

class Solution {
public:
    /**
     * Determine whether s3 is formed by interleaving of s1 and s2.
     * @param s1, s2, s3: As description.
     * @return: true of false.
     */
    bool isInterleave(string s1, string s2, string s3) {
        // write your code here
        if(s3.size() != s1.size() + s2.size())  
            return false;  
        vector<vector<bool> > dp(s1.size() + 1,vector<bool>(s2.size() + 1,false));
        dp[0][0] = true;  
        for(int i = 1;i <= s1.size();i++)  
            dp[i][0] = (dp[i - 1][0] && (s3[i - 1] == s1[i - 1]));  
        for(int i = 1;i <= s2.size();i++)  
            dp[0][i] = (dp[0][i - 1] && (s3[i - 1] == s2[i - 1]));  
        for(int i = 1;i <= s1.size();i++)  
        {  
            for(int j = 1;j <= s2.size();j++)  
            {  
                int t = i + j;  
                if(s1[i - 1] == s3[t - 1])  
                    dp[i][j] = dp[i][j] || dp[i - 1][j];  
                if(s2[j - 1] == s3[t - 1])  
                    dp[i][j] = dp[i][j]||dp[i][j - 1];  
            }  
        }  
        return dp[s1.size()][s2.size()]; 
    }
};
上一篇 下一篇

猜你喜欢

热点阅读