一道动态规划的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 ] = t r u e 当 且 仅 当 F [ i − 1 , j ] = = t r u e 且 s 1 [ i − 1 ] = = s 3 [ i + j − 1 ] 或 F [ i , j − 1 ] = = t r u e 且 s 2 [ j − 1 ] = = s 3 [ i + j − 1 ] 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] 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"
*/