2017多校训练赛第九场 HDU 6170 Two String(dp)

Two strings

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1723    Accepted Submission(s): 680

Problem Description

Giving two strings and you should judge if they are matched.
The first string contains lowercase letters and uppercase letters.
The second string contains lowercase letters, uppercase letters, and special symbols: “.” and “*”.
. can match any letter, and * means the front character can appear any times. For example, “a.b” can match “acb” or “abb”, “a*” can match “a”, “aa” and even empty string. ( “*” will not appear in the front of the string, and there will not be two consecutive “*”.

Input

The first line contains an integer T implying the number of test cases. (T≤15)
For each test case, there are two lines implying the two strings (The length of the two strings is less than 2500).

Output

For each test case, print “yes” if the two strings are matched, otherwise print “no”.

Sample Input

 
 
3 aa a* abb a.* abb aab

Sample Output

 
 
yes yes no

Source

2017 Multi-University Training Contest - Team 9



        最近发现,如果dp好能够快速解决很多问题,于是来补一波……

        这个题其实有点类似最长公共子串的dp,但是又略微有点不同。我们还是一样,设dp[i][j]表示第一个串取前i位,第二个串取前j位是否能够完成匹配。根据题意,如果第i位和第j位相等或者第j位为‘.',那么可以直接从前一位转移过来,有转移方程:dp[i][j]=dp[i-1][j-1]。

        然后就是重点讨论一下当第j位为’*‘的时候。这个符号表示它前一位可以重复n次,这个n可以是0,而当n为0的时候相当于去掉两位(第j位和前一位第j-1位),故可以从dp[i][j-2]转移过来。然后当n为1的时候,相当于第j位是空的,即第二个串只考虑到第j-1位,故可以从dp[i][j-1]转移过来。当n为2时,相当于j-1位重复了一次,必须满足a[i]==a[i-1]且b[j-1]==a[i],那么可以从dp[i-1][j-1]转移过来。最后是n大于2的情况,此时相当于是把前一位重复很多次,那么这个前提条件当然是a[i]==a[i-1]且b[j-1]==a[i],如此,就可以从dp[i-1][j]转移过来。

        总的来说这样就完成了dp。可以看出,这题还是很需要认真细致,不丢掉每一个细节的。具体见代码:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define N 2510
using namespace std;

char a[N],b[N];
bool dp[N][N];
int n,m;

int main()
{
    int T_T,T=0;
    cin>>T_T;
    while(T_T--)
    {
        scanf("%s",a+1);
        scanf("%s",b+1);
        n=strlen(a+1);
        m=strlen(b+1);
        memset(dp,0,sizeof(dp));
        dp[0][0]=1; if (b[2]=='*') dp[0][2]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if (a[i]==b[j]||b[j]=='.') dp[i][j]=dp[i-1][j-1];
                if (b[j]=='*')
                {
                    dp[i][j]=dp[i][j-1]|dp[i][j-2];
                    if (a[i]==a[i-1]) dp[i][j]=dp[i-1][j-1]|dp[i-1][j];
                }
            }
        }
        if (dp[n][m]) puts("yes"); else puts("no");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值