HDU 6170 Two strings(dp)

本文介绍了一种使用动态规划解决字符串匹配问题的方法。通过详细解释DP的状态定义、转移方程及其实现细节,帮助读者理解如何判断两个特定格式的字符串是否能够相互匹配。

题目:点击打开链接

题意:给定两个字符串,假设为串a,串b。a由大写字母和小写字母组成,b由大写字母,小写字母,”.“,”*“ 组成。其中”.“可以代替任何的一个字母,”*“与其一个前缀如a*可代替a,aa,aaa...,以及空。(在这里注意的是a*可以是空 意味着*前面的一个字符和*可以一起去掉而不是只有*被去掉 比赛的时候题意理解错了QAQ) 最后判断a,b是否匹配。

思路:比赛时暴力看错题没过,但是据说暴力是能过的。看题解给的一般是dp。

dp[i][j]表示b[1..i]与a[1..j]匹配是否成功

初始值dp[0][0]=true,字符串从1开始

当前状态b[i]==a[j]或者b[i]=='.',dp[i][j]=dp[i-1][j-1];

当前状态b[i]=='*',

1.先讨论用*匹配1位或0位

1)a*->a:dp[i][j]=dp[i-1][j]

2)a*->空:dp[i][j]=dp[i-2][j]

2.假设已用*匹配多位

1)假定b[1..i-1]==a[1..j-1]已经匹配完成且a[j]==a[j-1],  则当前位可与a[j]位相匹配,dp[i][j]=true

2)假定b[1..i]==a[1..j-1]已经匹配完成且a[j]==a[j-1],  则当前位可与a[j]位相匹配,dp[i][j]=true

3.特别的

如果i==2且b[i]=='*',那么dp[i][0]=true,表示当串b为两位的串且第二位上是* ,那么它可以跟空串匹配

代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=2505;
bool dp[maxn][maxn];
int main()
{
    int T,lena,lenb;
    char a[maxn],b[maxn];
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,false,sizeof(dp));
        scanf("%s%s",a+1,b+1);
        lena=strlen(a+1);
        lenb=strlen(b+1);
        dp[0][0]=true;
        for(int i=1;i<=lenb;i++)
        {
            if(i==2&&b[i]=='*')
                dp[i][0]=true;
            for(int j=1;j<=lena;j++)
            {
                if(a[j]==b[i]||b[i]=='.')
                    dp[i][j]=dp[i-1][j-1];
                if(b[i]=='*')
                {
                    dp[i][j]=dp[i-1][j]|dp[i-2][j];
                    if((dp[i-1][j-1]||dp[i][j-1])&&a[j]==a[j-1])
                        dp[i][j]=true;
                }
            }
        }
        if(dp[lenb][lena])
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值