1. 程式人生 > >leetcode 97. Interleaving String (hard)

leetcode 97. Interleaving String (hard)

一道動態規劃的hard級題目,雖然實際上也不算難。
因為上一週做的動態規劃題目的影響,開始的時候也沒有想著去寫狀態轉移方程,考慮直接用遞迴做記憶化搜尋(實際上就是暴力搜尋)

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        return isinter(s1,s2,s3,0,0,0);
    }
    
    bool isinter(string s1,string s2,string s3,int x,int y,int z)
    {
        if(
x == s1.size() && y == s2.size() && z == s3.size()) return true; else if(z == s3.size()) return false; bool match1 =false,match2 = false; if(x<s1.size()) { if(s1[x]==s3[z]) { match1 = isinter
(s1,s2,s3,x+1,y,z+1); } } if(match1) return true; if(y<s2.size()) { if(s2[y]==s3[z]) { match2 = isinter(s1,s2,s3,x,y+1,z+1); } } return match1||match2; } };

果不其然被卡了,題目中存在三位數及更高的資料。不用多項式級別的時間複雜度應該是過不去的。

然後想了一下狀態轉移方程,可以將對於s3是否為s1,s2的插入字串改為判斷s1的前i個字元與s2的前j個字元是否能夠構成等長的s3的字首的問題。

這樣子可以構造一個可行性函式F[i,j]表明構造這個字首的可能性,有F[i,j]=trueF[i1,j]==trues1[i1]==s3[i+j1]F[i,j1]==trues2[j1]==s3[i+j1]F[i,j]=true 當且僅當F[i-1,j]==true且s1[i-1]==s3[i+j-1]或F[i,j-1]==true且s2[j-1]==s3[i+j-1],即從s1的上一個字元推導而來或是從s2的上一個字元推導而來。

注意要進行合法性檢測。

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


class Solution {
public:
    int getIndex(int x,int y,int xmax)
    {
        return y*xmax+x;
    }

    bool isInterleave(string s1, string s2, string s3) {
        vector<int> calculate(26,0);
        for(int i = 0;i<s1.size() || i<s2.size() || i<s3.size();i++)
        {
            if(i<s1.size())
                calculate[s1[i]-'a']++;
            if(i<s2.size())
                calculate[s2[i]-'a']++;
            if(i<s3.size())
                calculate[s3[i]-'a']--;
        }
        for(int i = 0;i<26;i++)
        {
            if(calculate[i]!=0)
                return false;
        }


        vector<bool> possible((s1.size()+1)*(s2.size()+1),false);
        possible[0] = true;
        for(int i = 1;i<=s1.size();i++)
        {
            int index = getIndex(i,0,s1.size());
            if(s1[i-1]==s3[i-1])
                possible[index] = true;
            else
                break;
        }
        for(int j = 1;j<=s2.size();j++)
        {
            int index = getIndex(0,j,s1.size());
            if(s2[j-1]==s3[j-1])
                possible[index] = true;
            else
                break;
        }

        for(int i = 1;i<=s1.size();i++)
        {
            for(int j = 1;j<=s2.size();j++)
            {
                int index = getIndex(i,j,s1.size());
                if(possible[getIndex(i-1,j,s1.size())] && s1[i-1]==s3[i+j-1])
                {
                    possible[index] = true;
                }
                else if(possible[getIndex(i,j-1,s1.size())] && s2[j-1] == s3[i+j-1])
                {
                    possible[index] = true;
                }
            }
        }
        return possible[getIndex(s1.size(),s2.size(),s1.size())];
    }
};
int main(void)
{
    Solution s;
    cout<<s.isInterleave("","","a")<<endl;

    return 0;
}
/*
"bbbbbabbbbabaababaaaabbababbaaabbabbaaabaaaaababbbababbbbbabbbbababbabaabababbbaabababababbbaaababaa"
"babaaaabbababbbabbbbaabaabbaabbbbaabaaabaababaaaabaaabbaaabaaaabaabaabbbbbbbbbbbabaaabbababbabbabaab"
"babbbabbbaaabbababbbbababaabbabaabaaabbbbabbbaaabbbaaaaabbbbaabbaaabababbaaaaaabababbababaababbababbbababbbbaaaabaabbabbaaaaabbabbaaaabbbaabaaabaababaababbaaabbbbbabbbbaabbabaabbbbabaaabbababbabbabbab"
*/