Combine String(动态规划)

本文介绍了一种使用动态规划解决字符串组合匹配问题的算法,通过构建二维DP数组判断目标字符串是否能由两个源字符串组成,即使两字符串在目标中不连续。文章提供了详细的思路解析和AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  http://acm.hdu.edu.cn/showproblem.php?pid=5707
Problem Description
  Given three strings a, b and c, your mission is to check whether c is the combine string of a and b.
A string c is said to be the combine string of a and b if and only if c can be broken into two subsequences, when you read them as a string, one equals to a, and the other equals to b.
For example, "adebcf’’ is a combine string of "abc’’ and "def’’.
Input
  Input file contains several test cases (no more than 20). Process to the end of file.
Each test case contains three strings a, b and c (the length of each string is between 1 and 2000).
Output
  For each test case, print "Yes’’, if c is a combine string of a and b, otherwise print "No’’.
Sample Input
  abc
  def
  adebcf
  abc
  def
  abecdf
Sample Output
  Yes
  No

题意

  字符串匹配问题,判断 c 是否恰好由字符串 a 和 b 组成, a 为 c 的子串, b 也为 c 的子串,可以不连续。

思路

  dp[i][j] 表示字符串 c 的前 i + j 位是否可以由字符串 a 的前 i 位以及字符串 b 的前 j 位组成,dp[i][j]=true 表示是,dp[i][j]=false 表示不是,则 dp[i][j] 可以由 dp[i - 1][j] 和 dp[i][j - 1] 转移过来。
  如果 dp[i][j] 由 dp[i-1][j] 转移而来,那么应该满足:dp[i - 1][j] 是 true 且 a 的第 i 个字符必须等于 c 的第 i + j 个字符。
  如果 dp[i][j] 由 dp[i][j-1] 转移而来, 那么应该满足:dp[i][j - 1] 是 true 且 b 的第 j 个字符必须等于c 的第 i + j 个字符。

状态转移方程:

	if(can[i-1][j]&&a[i]==c[i+j]&&i>0) can[i][j]=true;
	if(can[i][j-1]&&b[j]==c[i+j]&&j>0) can[i][j]=true;

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cctype> 
#include<cstring>
#include<cstdlib>
const int maxn = 2010;
using namespace std;
bool can[maxn][maxn]; 
char a[maxn],b[maxn],c[maxn];
int main() 
{
    while(~scanf("%s",a+1)){
        scanf("%s",b+1);
        scanf("%s",c+1);
        int la = strlen(a+1);
        int lb = strlen(b+1);
        int lc = strlen(c+1);
        if((la+lb)!=lc){	//特判长度
            printf("No\n");
            continue;
        }
        memset(can,false,sizeof(can));	//初始化全为 false
        can[0][0]=true;	//没有字符时,应该看作 true
        for(int i=0;i<=la;i++){
            for(int j=0;j<=la;j++){
                if(can[i-1][j]&&a[i]==c[i+j]&&i>0) can[i][j]=true;
                if(can[i][j-1]&&b[j]==c[i+j]&&j>0) can[i][j]=true;
            }
        }
        if(can[la][lb])
            printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逃夭丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值