hdu 6170 Two strings

来源:互联网 发布:精英特速读软件 编辑:程序博客网 时间:2024/06/06 13:04

Problem

acm.hdu.edu.cn/showproblem.php?pid=6170

Meaning

有个文本串 a 和模式串 b,a 中只有字母,而 b 中还可能有.*,其中.可匹配任意一个字母,*表示它的前一个字母可以出现若干次(包括 0 次,保证*不是第一个字符)。问 a 能否和 b 匹配。

Analysis

dp[i][j]:a 串前 i 个字符是否能和 b 串前 j 个字符匹配
bj 是字母或.,那么只有dp[i-1][j-1]成立且 aibj 匹配时dp[i][j]才成立;
bj*,有两种情况:把它前面的那个字母去掉、把它前面那个字母复制若干次。
dp 的递推中,a 串的枚举是从“第 0 个字符”(字符串开始字符的前一个空的字符)开始,因为如果 b2*的话,能匹配 a 开头的一个“空串”。如样例:

aaa.*aaa

应该是yes
注意,当*前面的字符是.时,并不是.出现若干次,而是那个.匹配的那个字母出现若干次。

Code

#include <cstdio>#include <cstring>using namespace std;const int S = 2500;char a[S+3], b[S+3];bool dp[S+1][S+1];int main(){    int T;    scanf("%d", &T);    while(T--)    {        scanf("%s %s", a+1, b+1);        memset(dp, false, sizeof dp);        dp[0][0] = true;        int la = strlen(a + 1), lb = strlen(b + 1);        for(int i = 0; i <= la; ++i) // 从 0 开始            for(int j = 1; j <= lb; ++j)            {                if(dp[i][j]) // 防止下面的 for k 重复执行                    continue;                if(dp[i-1][j-1] && (a[i] == b[j] || b[j] == '.'))                    dp[i][j] = true;                else if(b[j] == '*')                {                    // 去除前面字符的情况                    if(dp[i][j-2])                        dp[i][j] = true;                    // 复制前面字符的情况                    if(dp[i][j-1])                        for(int k = i; k <= la && a[k] == a[i]; ++k)                            dp[k][j] = true;                }            }        puts(dp[la][lb] ? "yes" : "no");    }    return 0;}

p.s. 比赛时看见有人在研究正则表达式,不知道是不是在做这题…

原创粉丝点击