LeetCode87 Scramble String 混乱字符串 C++

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a

We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Example 1:

Input: s1 = "great", s2 = "rgeat"
Output: true

Example 2:

扫描二维码关注公众号,回复: 2163845 查看本文章
Input: s1 = "abcde", s2 = "caebd"
Output: false
题源: here;完整实现: here

思路:

三种方案:1 递归法;2 动态规划;3 基于记忆的递归。

这三种方法都基于一条更新规则:

f[n][i][j]} =  (f[k][i][j] && f[n-k][i+k][j+k]) 
            || (f[k][i][j+n-k] && f[n-k][i+k][j])
n表示字符串长度,i表示s1的起始位置,j表示s2的起始位置。

1 递归

bool recurse(string s1, int start1, int len, string s2, int start2){
	if (len == 1) return s1[start1] == s2[start2];
	for (int i = 1; i < len; i++){
		if ((recurse(s1, start1, i, s2, start2) && recurse(s1, start1 + i, len - i, s2, start2 + i)) ||
			(recurse(s1, start1, i, s2, start2 + len - i) && recurse(s1, start1 + i, len - i, s2, start2))
			){
			return true;
		}
	}

	return false;
}
bool isScramble(string s1, string s2) {
	if (s1.size() != s2.size()) return false;
	return recurse(s1, 0, s1.size(), s2, 0);
}

2 动态规划

bool isScramble2(string s1, string s2){
	if (s1 == s2) return true;
	if (s1.size() != s2.size()) return false;
	vector<vector<vector<bool>>> dp(s1.size() + 1, vector<vector<bool>>(s1.size(), vector<bool>(s1.size(), false)));
	for (int i = 0; i < s1.size(); i++){
		for (int j = 0; j < s1.size(); j++){
			dp[1][i][j] = s1[i] == s2[j];
		}
	}

	for (int len = 2; len <= s1.size(); len++){
		for (int i = 0; i < s1.size() - len + 1; i++){
			for (int j = 0; j < s1.size() - len + 1; j++){
				for (int subLen = 1; subLen < len && !dp[len][i][j]; subLen++){
					dp[len][i][j] = (dp[subLen][i][j] && dp[len - subLen][i + subLen][j + subLen]) ||
						(dp[subLen][i][j + len - subLen] && dp[len - subLen][i + subLen][j]);
				}
			}
		}
	}
	return dp[s1.size()][0][0];
}

3 基于记忆的递归

bool recurse2(string s1, int start1, int len, string s2, int start2, vector<vector<vector<int>>>& memo){
	if (memo[len][start1][start2] != -1) return  memo[len][start1][start2];

	if (len == 1){  
		memo[len][start1][start2] = s1[start1] == s2[start2] ? 1 : 0;
		return memo[len][start1][start2];
	} 

	for (int i = 1; i < len; i++){
		if ((recurse2(s1, start1, i, s2, start2, memo) && recurse2(s1, start1 + i, len - i, s2, start2 + i, memo)) ||
			(recurse2(s1, start1, i, s2, start2 + len - i, memo) && recurse2(s1, start1 + i, len - i, s2, start2, memo))
			){
			return memo[len][start1][start2] = 1;
		}
	}

	return memo[len][start1][start2] = 0;
}

bool isScramble3(string s1, string s2){
	if (s1 == s2) return true;
	if (s1.size() != s2.size()) return false;
	vector<vector<vector<int>>> memo(s1.size() + 1, vector<vector<int>>(s1.size(), vector<int>(s1.size(), -1)));
	return recurse2(s1, 0, s1.size(), s2, 0, memo);
}

猜你喜欢

转载自blog.csdn.net/m0_37518259/article/details/81022056
今日推荐