87. 扰乱字符串

要求:判断b是否由a切分换位得来,长度为1不切,大于1可以选择切和换位
思路:
法一:暴力法首先判断两个字符串词频是否一样,然后遍历所有的i即所有长度的串,检测字符串是否交换过,递推到长度为1或者字符串相等。可以记忆化搜索

class Solution {
public:
	vector<vector<vector<int>>> cache;
	string s1, s2;
	int n;
	int NO = -1, YES = 1, EMPTY = 0;

    bool isScramble(string _s1, string _s2) {
    	s1 = _s1, s2 = _s2;
    	if(s1 == s2) return true;
    	if(s1.size() != s2.size()) return false;
    	n = s1.size();
    	cache.resize(n, vector<vector<int>>(n, vector<int>(n+1, 0)));

    	return dfs(0, 0, n);
    }

    bool dfs(int i, int j, int len) {
    	if(cache[i][j][len] != EMPTY)
    		return cache[i][j][len] == YES;

    	string a = s1.substr(i, len), b = s2.substr(j, len);
    	
    	if(a == b)
    		return cache[i][j][len] = YES || true;

    	if(!check(a, b))
    		return cache[i][j][len] = NO && false;

    	for(int k = 1; k < len; k++) {
    		if(dfs(i, j, k) && dfs(i+k, j+k, len-k))
    			return cache[i][j][len] = YES || true;

    		if(dfs(i, j+len-k, k) && dfs(i+k, j, len-k))
    			return cache[i][j][len] = YES || true;
    	}

    	cache[i][j][len] = NO;
    	return false;
    }

    bool check(string s1, string s2) {
    	if(s1.size() != s2.size()) return false;
    	vector<int> cnt1(26,0), cnt2(26,0);
    	for(auto c : s1)
    		cnt1[c-'a']++;
    	for(auto c : s2)
    		cnt2[c-'a']++;
    	return cnt1 == cnt2;
    }

};

法二:动态规划,参考上面的记忆化dfs部分即可

class Solution {
public:
    bool isScramble(string s1, string s2) {
    	if(s1 == s2) return true;
    	if(s1.size() != s2.size()) return false;

    	int n = s1.size();
    	vector<vector<vector<int>>> f(n, vector<vector<int>>(n, vector<int>(n+1, 0)));

    	// 先处理长度为 1 的情况
    	for(int i = 0; i < n; i++) {
    		for(int j = 0; j < n; j++) {
    			if(s1[i] == s2[j])
    				f[i][j][1] = 1;
    		}
    	}

    	// 再处理其余长度情况
    	for(int len = 2; len <= n; len++) {
    		for(int i = 0; i+len <= n; i++) {
    			for(int j = 0; j+len <= n; j++) {
    				for(int k = 1; k < len; k++) {
    					bool a = f[i][j][k] && f[i+k][j+k][len-k];
    					bool b = f[i][j+len-k][k] && f[i+k][j][len-k];
    					if(a || b) 
    						f[i][j][len] = true;
    				}
    			}
    		}
    	}
    	return f[0][0][n];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值