交错字符串——动态规划

题目描述:

给定三个字符串A, B, C,判断C是否由A和B交错构成。交错构成的意思是,对于字符串C,可以将其每个字符标记为A类或B类,使得我A类的每个字符顺序构成了A字符串,B类的每个字符顺序构成了B字符串。如:对于A=”rabbit” B=”mq”, ”rabmbitq”是由A和B交错构成的,但”rabbqbitm”不是由A和B交错构成。


解题思路:


1、直接顺序比较,从C中依次拿掉A,看剩下的是不是等于B,若是则返回true,否则,返回false. 但是如果A和B中有相同的字符,则这种方法会出错。

例如,A=“aa”, B=“ab”,C=“aaba”  这种情况下,上述这种方法会返回false,但实际上它是true。 因此这种方法不可行。


2、采用动态规划的方法

定义状态:dp[i][j] 代表是A的前i个字符与C中匹配,B中前j个字符与C中匹配.


递推的比较过程中如果知道s1,s2上的指针p,q的情况,s3上这个指针肯定在p+q的位置。利用这个结论,就可以设计出O(m1*m2)的DP方案。

执行操作分为两步,分别判断:

A[i-1] == C[i+j-1]  为真,则 dp[i][j] = dp[i][j] || dp[i-1][j] 


B[j-1] == C[i+j-1] 为真,则dp[i][j] = dp[i][j] || dp[i][j-1]

最后返回:dp[i][j],此时,i=s1.lenth(),  j=s2.length()


参考代码:

#include"iostream"
#include"vector"
using namespace std;

class Solution
{
public:
	bool isInterleave(string s1, string  s2, string s3)
	{
		size_t len1, len2;
		len1 = s1.length();
		len2 = s2.length();

		if (len1 + len2 != s3.length())
			return false;
		vector> dp;//定义变量
		dp.resize(len1 + 1, vector(len2 + 1, false));//分配空间

		dp[0][0] = true;
		for (int i = 0; i <= len1 ;i++)
		for (int j = 0; j <= len2 ; j++)
		{
			if (i == 0 && j == 0) 
				continue;

			if (i>0){
				if (s1[i - 1] == s3[i + j - 1]){
					dp[i][j] = dp[i][j] || dp[i - 1][j];
				}
			}
			if (j>0){
				if (s2[j - 1] == s3[i + j - 1]){
					dp[i][j] = dp[i][j] || dp[i][j - 1];
				}
			}
		}
		bool result = dp[len1][len2];
		return result;
	}
};

int main()
{
	Solution S;
	string s1 = "aa";
	string s2 = "ab";
	string s3 = "aaba";
	bool ans = S.isInter(s1, s2, s3);
	if (ans)
		cout << "true" << endl;
	else
		cout << "false" << endl;


}


这道题目跟最长公共子序列有点相似,思路类似,稍作变换.

LCS是判断一个串,这个题目是同时判断两个串。




你可能感兴趣的:(算法学习,动态规划,算法,字符串交错)