HDU_6170 Two strings 【DP】

题目链接

题目描述

给定一个文本串和一个匹配串,问匹配串是否可以构成文本串,如果可以构成就输出”yes”,否则就输出”no”。
文本串和匹配串都由大小写构成,但是匹配串当中包含了特殊的字符:’.’可以代替任意一种的字符,’*’可以将上一个字符前面与他相同的删除,也可以无限将前面的字符向后拓展,也可以不做任何操作。

解题思路

DP思想,开一个二维的dp数组,存放匹配串和文本串分别为i,j时 是否满足匹配。如果满足,值为真,否则值为假,最后判断dp[len2][len1]是否为真即可。
DP的思想

  • 当文本串和匹配串相同,或者匹配串为.则满足为真的条件但要注意这里的dp应该是dp[i][j] = dp[i - 1][j - 1];只有前面都满足这才能为真。
  • 当匹配串的字符为 * ,当匹配串为*的时候,可以进行向前删除也可以向后填充字符,满足其中一个那么dp[i][j] = true;
  • 特殊情况第二个为可以起到删除前面的字符的作用,所以dp[i][0] = true;

代码部分

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4;
bool dp[maxn >> 1][maxn >> 1]; //存放的是匹配串和文本串分别为i,j时 是否满足匹配
char s1[maxn >> 1];//文本串
char s2[maxn >> 1];//匹配串

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t --)
    {
        cin >> s1 + 1;
        cin >> s2 + 1;
        memset(dp, false, sizeof(dp));
        dp[0][0] = true;
        int len1 = strlen(s1 + 1);
        int len2 = strlen(s2 + 1);
        for(int i = 1; i <= len2; ++ i)
        {
            ///当匹配串第二个为*的时候就说明dp[i][0]都可以匹配,因为它可以把前面的字符给删掉
            if(i == 2 && s2[i] == '*') dp[i][0] = true;
            for(int j = 1; j <= len1; ++ j)
            {
                ///当匹配字符为.的时候或者文本串和匹配串相等的时候,dp[i][j]都等于前一个状态
                if(s2[i] == '.' || s1[j] == s2[i]) dp[i][j] = dp[i - 1][j - 1];
                else
                {
                    if(s2[i] == '*')
                    {
                        ///当匹配串为*的时候,可以进行向前删除也可以向后填充字符,满足其中一个那么dp[i][j] 都为真
                        ///满足删除的条件dp[i][j]为真
                        dp[i][j] = dp[i - 1][j] | dp[i - 2][j];
                        ///这个就是代表*可以像后面填充相同字符,然后dp[i][j]为真
                        if((dp[i - 1][j - 1] || dp[i][j - 1]) && s1[j - 1] == s1[j]) dp[i][j] = true;
                    }
                }
            }
        }
        puts(dp[len2][len1]?"yes":"no");
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值