LeetCode Interleaving String

本文介绍了一种用于判断字符串s3是否能由s1和s2交错组成的高效算法。通过使用动态规划方法,避免了递归过程中的重复计算,显著提高了算法效率。

题目

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

 

判断s3是否可以有s1,s2由前向后交错取字符构成。

不难想到递归版本,但是特殊情况下:s1,s2重复较多时效率很低,必然超时。

其实即是一个子问题重复调用的问题,通过表格记录可以稍稍提高效率,即可AC。

 

更高效的方法dp。

flag[i][j]记录s1[i]开始、s2[j]开始的两个子串是否可以和s3[i+j]开始的子串匹配。

如果s1[i]==s3[i+j]且s1[i+1]开始、s2[j]开始的子串和s3[i+j+1]开始的子串匹配;

或者s2[j]==s3[i+j]且s1[i]开始、s2[j+1]开始的子串和s3[i+j+1]开始的子串匹配;

则s1[i]开始、s2[j]开始的两个子串可以和s3[i+j]开始的子串匹配。

由s3尾向前递推。

 

代码:

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
		if(s3.size()!=s1.size()+s2.size())
			return false;
		vector<vector<bool>> flag(s1.size()+1,vector<bool>(s2.size()+1,false));	//s1[p1],s2[p2]开始的串可以和s3[p1+p2]开始的串匹配的标志
		flag[s1.size()][s2.size()]=true;	//超尾可以匹配
		for(int len=1;len<=s3.size();len++)	//dp,s[3]长度递增,从后向前扫描
		{
			for(int i=0;i<=min(len,(int)s1.size());i++)	//s1使用的长度递增
			{
				int j=len-i;	//确定s2需要的长度
				if(j>s2.size())
					continue;
				if(i==0)	//仅用s2匹配
				{
					if(flag[s1.size()][s2.size()-j+1]&&s2[s2.size()-j]==s3[s3.size()-len])
						flag[s1.size()][s2.size()-j]=true;
				}
				else if(j==0)	//仅用s1匹配
				{
					if(flag[s1.size()-i+1][s2.size()]&&s1[s1.size()-i]==s3[s3.size()-len])
						flag[s1.size()-i][s2.size()]=true;
				}
				else if(s1[s1.size()-i]==s3[s3.size()-len]&&flag[s1.size()-i+1][s2.size()-j])	//s1[p1+1],s2[p2]可以匹配,且s1[p1]==s3[p3]
					flag[s1.size()-i][s2.size()-j]=true;
				else if(s2[s2.size()-j]==s3[s3.size()-len]&&flag[s1.size()-i][s2.size()-j+1])	//s1[p1],s2[p2+1]可以匹配,且s2[p2]==s3[p3]
					flag[s1.size()-i][s2.size()-j]=true;
			}
		}
		return flag[0][0];
    }
};


 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值