【DP】HDU 6170/2017多校9 1010 Two strings

本文介绍一种基于动态规划的正则表达式匹配算法,用于判断两个字符串是否匹配。通过预处理第二个字符串中的特殊符号,并利用二维数组进行状态转移,最终实现对复杂模式的有效匹配。

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

题目:
HDU 6170
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


分析:
较简单的DP
f[i][j]为a串前i个与b串前j个是否匹配 1:匹配 0:不匹配
先将b串的’*’的前一个字符单独记录下来(p数组中),然后删掉,成为新的b串

  1. f[i][j]=f[i-1][j-1]&&(a[i]==b[j]); b[j]为字母
  2. f[i][j]=f[i-1][j-1]; b[j]为’.’
  3. f[i][j]=f[i][j]||f[i-1][j]||f[i-1][j-1]; fla[i][j]=1;b[j]为’*’且p[j]=’.’且fla[i][j]=0;
  4. f[i][j]=f[i][j]||f[i-1][j]&&(a[i]==a[i-1]);b[j]为’*’且p[j]=’.’且fla[i][j]=1;
  5. f[i][j]=f[i][j-1]||(f[i-1][j]&&(a[i]==p[j])); b[j]为’*’且p[j]为字母

    • fla[i][j] 用来标记”.*”中的’.’是否已经与某个字符匹配
      (”.*”必须与相同的多个字符串匹配,如”aaaaa“或”bbb“,不能是”absaf“,因为题意不清WA了一发 = =)

想清楚后,代码很easy

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring> 
#include<vector>  
using namespace std;

const int maxn=2600;
char a[maxn],b[maxn],p[maxn];
int la,lb,t,tmp,f[maxn][maxn];
bool fla[maxn][maxn];

void pre (){
    int i,j;
    la=strlen (a+1);
    tmp=strlen (b+1);
    lb=0;
    for (i=1;i<=tmp;i++){
        if (b[i+1]!='*'){
            b[++lb]=b[i];
        }
        else {
            p[++lb]=b[i];
            b[lb]='*';
            i++;
        }
    }
}

void work (){
    int i,j,k;
    memset (f,0,sizeof (f));
    memset (fla,0,sizeof (fla));
    f[0][0]=1;

    for (i=1;i<=lb;i++){
        if (f[0][i-1]){
            if (b[i]=='*')f[0][i]=1;
        }
        else break;
    }

    for (i=1;i<=la;i++){
        for (j=1;j<=lb;j++){
            if (b[j]>='a'&&b[j]<='z'||b[j]>='A'&&b[j]<='Z'){
                f[i][j]=f[i-1][j-1]&&(a[i]==b[j]);
            }
            else if (b[j]=='.'){
                f[i][j]=f[i-1][j-1];
            }
            else {
                if (p[j]=='.'){
                    f[i][j]=f[i][j-1]; 
                    if (f[i][j])continue;
                    if (!fla[i-1][j]){//没有匹配 
                        f[i][j]=f[i][j]||f[i-1][j]||f[i-1][j-1];
                        fla[i][j]=1;
                    }
                    else {
                        f[i][j]=f[i][j]||f[i-1][j]&&(a[i]==a[i-1]);
                    }
                }
                else {
                    f[i][j]=f[i][j-1]||(f[i-1][j]&&(a[i]==p[j]));
                }
            }
        }
    }
    if (f[la][lb]){
        printf ("yes\n");
    }
    else printf ("no\n");
}

int main (){
    scanf ("%d",&t);
    while (t--){
        scanf ("%s%s",a+1,b+1);
        pre ();
        work ();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值