Leetcode抄答案之 87-扰乱字符串

题目描述:使用下面描述的算法可以扰乱字符串 s 得到字符串 t :
如果字符串的长度为 1 ,算法停止
如果字符串的长度 > 1 ,执行下述步骤:
在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。
随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。
在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算法。
给你两个 长度相等 的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。如果是,返回 true ;否则,返回 false 。

示例如下:
输入:s1 = “great”, s2 = “rgeat”
输出:true
解使:其实我不想放解释了,我看不懂解释


然后呢,这个题主要是动态规划里面一个问题,可以用区间dp来解决。
区间dp就是建立在区间搜索上的动态规划。其实是有一个模板的,大概是以下几步

//初始化dp数组
//枚举区间长度
//枚举起始点
//枚举终点
//枚举分割点

如这个题中,需要分割为两个字符串,步骤可为以下

//枚举区间长度
for (len=2;len<=Length_1;len++){
	//枚举第一个字符串起点
	for (i=0;i<=Length_1-len;i++){
		//枚举第二个字符串起点
		for (j=0;j<=Length_1-len;j++){
			//枚举分割点
			for (k=1;k<=len-1;k++){
				//balabala
			}		
		}
	}
}

动态规划最重要的就是状态方程,这里有两个情况
s1_left | s1_rights2_left | s2_right

  1. 分割完以后,不交换位置。即s1_left对应s2_left
  2. 交换位置,即s1_left对应s2_right

这里可以设置一个数组dp[i][j][t][k],用来表示s1[i:j]和s2[t:k]是否匹配。
因为区间长度肯定一样,所以可以再化简一下,变成dp[i][j][k],即s1和s2的起点分别为i和j,区间长度为k。
然后状态方程的话,如下判断

//情况1
dp[i][j][k]==1 && dp[i+k][j+k][len-k]==1
//情况2
dp[i][j+len-k][k]==1 && dp[i+k][j][len-k]==1

在判断赋值的时候都用k在每个小区间进行遍历,即先用len划分一个一个大区间,在每个区间里用k划分两个小区间,判断是否匹配。
然后dp[0][0][len]就是最终结果了。

然后还要对初始空间初始化,当区间为1的时候,所有都匹配。

for (i=0;i<Length_1;i++){
	for (j=0;j<Length_1;j++){
		if (s1.charAt(i)==s2.charAt(j))
			dp[i][j][1]=1;
		else
			dp[i][j][1]=-1;
	}
}

完整代码

static boolean isScramble(String s1, String s2) {
	int Length_1=s1.length(),Length_2=s2.length();
	if (Length_1!=Length_2)
		return false;
	int[][][] dp=new int[Length_1][Length_1][Length_1+1];
	int i=0,j=0,len=0,k=0;
	for (i=0;i<Length_1;i++){
		for (j=0;j<Length_1;j++){
			if (s1.charAt(i)==s2.charAt(j))
				dp[i][j][1]=1;
			else
				dp[i][j][1]=-1;
		}
	}
	//kaishi
	for (len=2;len<=Length_1;len++){
		for (i=0;i<=Length_1-len;i++){
			for (j=0;j<=Length_1-len;j++){
				for (k=1;k<=len-1;k++){
					if (dp[i][j][k]==1 && dp[i+k][j+k][len-k]==1)
						dp[i][j][len]=1;
					if (dp[i][j+len-k][k]==1 && dp[i+k][j][len-k]==1)
						dp[i][j][len]=1;
				}
				
			}
		}
	}
	return dp[0][0][Length_1]==1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值