hdu1501 Zipper(dfs && dp)

本文探讨了字符串匹配问题的解决方案,通过对比深搜和dp算法,展示了如何有效解决此类问题。深入分析了算法实现细节,并通过实例演示了如何在不同情况下选择最优策略。

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

挺不错的题。第一反应是模拟字符串匹配,但第二个样例就否定了。

str1 = cat, str2 =  tree, str = catrtee,当主串匹配到第四个字符t时,问题来了,是匹配第一个的还是第二个的?模拟的话两个判断条件会有个顺序,但一旦有顺序就会导致其中一种匹配不成功,所以换思路。


一种是简单的深搜,一种是简单的dp,思路都很清晰。


dfs:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <string>
#include <iostream>

using namespace std;

const int N = 1 << 16;
const int INF = 1e8;

string str1, str2, str;
bool pos;
int vis[205][205];

void dfs(int s1, int s2, int s)
{
    if(s1 == str1.length() && s2 == str2.length())
    {
        pos = true;
        return;
    }
    if(str1[s1] != str[s] && str2[s2] != str[s]) return;
    if(vis[s1][s2]) return;
    if(pos) return;
    vis[s1][s2] = 1;
    if(str1[s1] == str[s]) dfs(s1 + 1, s2, s + 1);
    if(str2[s2] == str[s]) dfs(s1, s2 + 1, s + 1);
}

int main()
{
  //   freopen("in.txt", "r", stdin);
    int t, n, Case = 1;
    scanf("%d", &t);
    while(t --)
    {
        cin >> str1 >> str2 >> str;
        pos = false;
        memset(vis, 0, sizeof(vis));
        dfs(0, 0, 0);
        if(pos) printf("Data set %d: yes\n", Case ++);
        else printf("Data set %d: no\n", Case ++);
    }
    return 0;
}


dp:注意对边界的处理,初始化条件为主串长度的字符相同即为1,否则为0。由于其是从1开始dp,所以把三个串的首字符也初始化。

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <string>
#include <iostream>

using namespace std;

const int N = 205;
const int INF = 1e8;

char str1[N], str2[N], str[N * 2];
int dp[N][N];

int main()
{
  //   freopen("in.txt", "r", stdin);
    int t, n, Case = 1;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%s%s%s", str1 + 1, str2 + 1, str + 1);
        str[0] = str1[0] = str2[0] = '0';
   //     memset(dp, 0, sizeof(dp));
        for(int i = 1; i < strlen(str1); i ++)
        {
            if(str1[i] == str[i]) dp[i][0] = 1;
            else dp[i][0] = 0;
        }
        for(int i = 1; i < strlen(str2); i ++)
        {
            if(str2[i] == str[i]) dp[0][i] = 1;
            else dp[0][i] = 0;
        }
        for(int i = 1; i < strlen(str1); i ++)
        {
            for(int j = 1; j < strlen(str2); j ++)
            {
                dp[i][j] = ((dp[i - 1][j] && str1[i] == str[i + j]) || (dp[i][j - 1] && str2[j] == str[i + j]));
            }
        }
        if(dp[strlen(str1) - 1][strlen(str2) - 1]) printf("Data set %d: yes\n", Case ++);
        else printf("Data set %d: no\n", Case ++);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值