题目:点击打开链接
题意:给定两个字符串,假设为串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;
}