dp:交错字符串

Leetcode, InterleavingString

力扣官方题解
设状态 f[i][j],表示 s1[0,i] 和 s2[0,j],匹配 s3[0, i+j]。如果 s1 的最后一个字符等于 s3 的最后一个字符,则 f[i][j]=f[i-1][j];如果 s2 的最后一个字符等于 s3 的最后一个字符,
则 f[i][j]=f[i][j-1]。因此状态转移方程如下:
f[i][j] = (s1[i - 1] == s3 [i + j - 1] && f[i - 1][j])
|| (s2[j - 1] == s3 [i + j - 1] && f[i][j - 1]);

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

template<typename Inlt>
bool isInterleave(Inlt first1, Inlt last1, Inlt first2, Inlt last2,
	Inlt first3, Inlt last3)
{
	if (first3 == last3)
		return first1 == last1 && first2 == last2;

	return (*first1 == *first3
		&& isInterleave(std::next(first1), last1, first2, last2, std::next(first3), last3))
		|| (*first2 == *first3
			&& isInterleave(first1, last1, std::next(first2), last2, std::next(first3), last3));
}

//递归,会超时,仅用来帮助理解
//vs2017 string end报错
bool solution(string s1, string s2, string s3)
{
	if (s3.length() != s1.length() + s2.length())
		return false;
	
	return isInterleave(begin(s1), end(s1), begin(s2), end(s2),
		begin(s3), end(s3));
}

//二维动规,时间复杂度 O(n^2),空间复杂度 O(n^2)
bool solution1(string s1, string s2, string s3)
{
	if (s3.length() != s1.length() + s2.length())
		return false;
	vector<vector<bool>> vec(s1.length() + 1, vector<bool>(s2.length() + 1, true));
	//特例 s2为空
	for ( size_t i = 1; i <= s1.length(); ++i )
		vec[i][0] = vec[i - 1][0] && s1[i - 1] == s3[i - 1];
	//特例 s1为空
	for (size_t i = 1; i <= s2.length(); ++i)
		vec[0][i] = vec[0][i - 1] && s2[i - 1] == s3[i - 1];

	for ( size_t i = 1; i <= s1.length(); ++i )
	{
		for ( size_t j = 1; j <= s2.length(); ++j )
		{
			vec[i][j] = (s1[i - 1] == s3[i + j - 1] && vec[i - 1][j]
				|| s2[j - 1] == s3[i + j - 1] && vec[i][j - 1]);
		}
	}
	return vec[s1.length()][s2.length()];
}

//二维动规 + 滚动数组,时间复杂度 O(n^2),空间复杂度 O(n)
bool solution2(string s1, string s2, string s3)
{
	if (s3.length() != s1.length() + s2.length())
		return false;
	if (s1.length() < s2.length())
		return solution2(s2, s1, s3);

	vector<bool> vec(s2.length() + 1, true);
	for (size_t i = 1; i < s2.length(); ++i)
		vec[i] = s2[i - 1] == s3[i - 1] && vec[i - 1];
	for (size_t i = 1; i < s1.length(); ++i)
	{
		vec[0] = s1[i - 1] == s3[i - 1] && vec[0];

		for (size_t j = 1; j <= s2.length(); ++j)
		{
			vec[j] = (s1[i - 1] == s3[i + j - 1] && vec[j])
				|| ( s2[j - 1] == s3[i + j - 1] && vec[j - 1] );
		}
	}
	return vec[s2.length()];
}


int main()
{
	{
		string s1 = "aabcc", s2 = "dbbca";
		string s3 = "aadbbcbcac";
		cout << solution2(s1, s2, s3) << endl;	//true
	}
	{
		string s1 = "aabcc", s2 = "dbbca";
		string s3 = "aadbbbaccc";
		cout << solution2(s1, s2, s3) << endl;	//false
	}
	{
		string s1 = "", s2 = "";
		string s3 = "";
		cout << solution2(s1, s2, s3) << endl;	//true
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值