LeetCode Scramble String

本文介绍了一种通过分治及动态规划方法解决字符串乱序匹配问题的算法,并提供了两种实现方式,一种为递归实现,另一种为动态规划实现,后者速度更快。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好题呀,太长时间不思考了,想到了分治方法,没坚持下去,也就没想出来,其实不难,就是把s1分为两个串a1,a2;s2分为两个串b1,b2,只要长度相同而且能对应上(就是可以通过交换得来)就可以了,然后递归判断每个子串。下面是递归的方案:

bool isScramble(string s1, string s2) {
	int lens1,lens2;
	lens1 = s1.length();
	lens2 = s2.length();
	if(lens1!=lens2)
		return false;
	if(lens1==0)
		return true;
	if (lens1==1)
	{
		return s1[0]==s2[0];
	}
	if (lens2==2)
	{
		return (s1[0]==s2[0]&&s1[1]==s2[1])||(s1[0]==s2[1]&&s1[1]==s2[0]);
	}
	string stra1,stra2,strb1,strb2;
	for(int i=1;i<lens1;i++)
	{
		stra1 = s1.substr(0,i);
		stra2 = s1.substr(i,lens1-i);
		strb1 = s2.substr(0,i);
		strb2 = s2.substr(i,lens2-i);
		if (isScramble(stra1,strb1)&&isScramble(stra2,strb2))
		{
			return true;
		}
		stra1 = s1.substr(0,lens1-i);
		stra2 = s1.substr(lens1-i,i);
		if (isScramble(stra1,strb2)&&isScramble(stra2,strb1))
		{
			return true;
		}
	}
	return false;
}
下面是别人的动态规划方法,看似复杂,其实也不难,所以才是好题呀,没做出来,白瞎了。

class Solution {
private:
	bool f[100][100][100];
public:
	bool isScramble(string s1, string s2) {
		// Start typing your C/C++ solution below
		// DO NOT write int main() function
		if (s1.size() != s2.size())
			return false;

		for(int i = 0; i < s1.size(); i++)
			for(int j = 0; j < s2.size(); j++)
				f[1][i][j] = (s1[i] == s2[j]);

		for(int len = 2; len <= s1.size(); len++)
		{
			for(int s1Beg = 0; s1Beg < s1.size(); s1Beg++)
			{
				int s1End = s1Beg + len - 1;
				if (s1End >= s1.size())
					break;

				for(int s2Beg = 0; s2Beg < s2.size(); s2Beg++)
				{
					int s2End = s2Beg + len - 1;
					if (s2End >= s2.size())
						break;

					f[len][s1Beg][s2Beg] = false;    
					for(int s1Mid = s1Beg; s1Mid < s1End; s1Mid++)
					{
						int leftSize = s1Mid - s1Beg + 1;
						int rightSize = len - leftSize;
						int s2Mid = s2Beg + leftSize - 1;
						bool res1 = f[leftSize][s1Beg][s2Beg] && f[rightSize][s1Mid+1][s2Mid+1];

						s2Mid = s2End - leftSize;
						bool res2 = f[leftSize][s1Beg][s2Mid+1] && f[rightSize][s1Mid+1][s2Beg];

						f[len][s1Beg][s2Beg] = f[len][s1Beg][s2Beg] || res1 || res2;
					}
				}
			}
		}

		return f[s1.size()][0][0];
	}
};

下面的方法是过了两天重新思考后自己写,思路还是一样的,但时间比上面的算法快了一倍。可能是上面算法中每次调用size函数增加了不少时间。别的也没什么差别。

bool isScramble03(string s1, string s2) {
	int lens1,lens2;
	lens1 = s1.length();
	lens2 = s2.length();
	if(lens1!=lens2)
		return false;
	if(lens1==0)
		return true;
	if (lens1==1)
	{
		return s1[0]==s2[0];
	}
	if (lens2==2)
	{
		return (s1[0]==s2[0]&&s1[1]==s2[1])||(s1[0]==s2[1]&&s1[1]==s2[0]);
	}
	bool dp[100][100][100];
	for (int i=0;i<lens1;i++)
	{
		for (int j=0;j<lens2;j++)
		{
			dp[1][i][j] = (s1[i]==s2[j]);
		}
	}
	int i,j,k,t;
	for (k=2;k<=lens1;k++)
	{
		for (i=0;i<lens1;i++)
		{
			if(i+k>lens1)
				break;
			for (j=0;j<lens2;j++)
			{
				if(j+k>lens2)
					break;
				for (t=1;t<k;t++)
				{	
					if (dp[t][i][j]&dp[k-t][i+t][j+t]|dp[t][i][j+k-t]&dp[k-t][i+t][j])
					{
						dp[k][i][j] = true;
						break;
					}
				}
				if(t==k)
					dp[k][i][j] = false;
			}
		}
	}
	return dp[lens1][0][0];
}

路是走出来,不是想出来的。这种方法也是慢慢想出来的,开始没思路,举了几个简单的例子就有思路了,一点点就总结出规律来了,凡事都如此吧,放弃了,就是永远失败了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值