java字符串匹配dp_Java数据结构与算法之交错字符串97(DP)

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

b7928a2b2242cd802658e84f724510c0.png

思路分析

当我看到这道题的第一想法是用三指针的方法解决:index1指向s1,index2指向s2,index3指向s3。按照顺序判断s3的字符是否与s1、s2的字符一致,即先与s1判断,不一致再与s2判断;若都不一样则输出false。

但这个解法在随后的测试中暴露了问题,与s1、s2比较是存在先后顺序的,所以如果s2出现s3的前部,则会出现问题。

比如"aa" "ab" "abaa"这个案例中,结果显示false,明显是错误的。

所以基于以上的问题,我们重新考虑问题。使用动态规划解题。我们依旧使用上面的案例进行解释。

首先考虑边界条件,s1.length()+s2.length() != s3.length()这种情况那么必然输入false;

s1.length()+s2.length() == s3.length()时,我们可以利用DP思想解决这个问题;

定义dp[i][j]为s1的前i个元素和s2的前j个元素是否可以组合成s3的前i+j个元素;

因此想要判断dp[i][j]位置的状态需要知道dp[i-1][j]或dp[i][j-1]的状态,换言之,只有dp[i-1][j]或dp[i][j-1]为true才会有dp[i][j]的进一步判断;

dp[i-1][j]代表s1的前i-1个元素和s2的前j个元素的组合状态。那么s1的第i-1元素呢,它是否可以组合为s3的第i+j-1元素呢?

所以dp[i-1][j]与s1.charAt(i-1) == s3.charAt(i+j-1)才是dp[i][j]的真实状态;反之dp[i][j-1]亦然;

DP的初始状态dp[0][0]必然为true。

所以我们可以推导出动态规划方程为:dp[i][j] = (dp[i-1][j] && s1.charAt(i-1) == s3.charAt(i+j-1)) || (dp[i][j-1] && s2.charAt(j-1) == s3.charAt(i+j-1))

代码实现

class Solution {

public boolean isInterleave(String s1, String s2, String s3) {

int index1 = s1.length(), index2 = s2.length();

if(s3.length() != index1+index2) {

return false;

}

boolean[][] dp = new boolean[index1+1][index2+1];

dp[0][0] = true;

// 为什么这儿要从0开始遍历呢?这就是三指针的问题所在。

// 当s3的开头字符是s2,这样在i=0的情况下就可以先搜索s2字符串了。

for(int i = 0; i <= index1; i++) {

for(int j = 0; j <= index2; j++) {

int p = i+j-1;

if(i > 0) {

// 这儿不加dp[i][j]的原因是先判断if(i > 0)

// 如果i<0,那么dp[i][j]就是默认值false,不影响下面的执行

dp[i][j] = dp[i-1][j] && s1.charAt(i-1) == s3.charAt(p);

}

if(j > 0) {

// 这儿为什么要加dp[i][j]?

// 如果在if(i > 0)中已经判断为true了,则不用再判断了

// 如果在if(i > 0)中已经判断为false了,则继续判断在if(j > 0)条件下是否满足

dp[i][j] = dp[i][j] || dp[i][j-1] && s2.charAt(j-1) == s3.charAt(p);

}

}

}

return dp[index1][index2];

}

}

执行结果

b0fefa532faa1e5353d82dc1371dc1b9.png

来源:https://www.cnblogs.com/njuptzheng/p/13338257.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值