题意:给两个字符串,第一个字符串只包括大写字母和小写字母,第二个字符串包括大小写字母和 ' . ',' * '。.字符可以替换成任何字符,* 字符可以换成第二个字符串*之前的那个字符,问:第二字符串能否通过一系列变换得到第一个字符串。
思路:令dp[i][j]代表b串中[1~i]和a串中[1~j]的字符是否匹配,匹配为1,不匹配为0,有以下状态转移关系:
1. 当
b[i]==′.′
或者
b[i]==a[j]
时,此时
dp[i][j]=dp[i−1][j−1]
2. 当
b[i]==′∗′
时,则匹配一个或者不匹配都合法,那么就由
dp[i−2][j]
或
dp[i−1][j]
转移而来,因为
′∗′
可以匹配任意数量的字符,所以还要判断假如
a[j−1]与b[i−1]
已成功匹配,并且
a[j−1]==a[j]
,显然当前的 * 可以继续匹配这一个字符,因此
dp[i][j]=1
,假如
a[j−1]与b[i]
已成功匹配(当前 * 可能已经成功匹配很多位),且
a[j−1]==a[j]
,则可以继续匹配这一个字符,因此dp[i][j]=1
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
#define LL long long
#define siz 2505
using namespace std;
char S[siz];
char T[siz];
int dp[siz][siz];
void solve()
{
int slen = strlen(S);
int tlen = strlen(T);
bool flag = true;
//cout<<slen<<" "<<tlen<<endl;
for(int i=0; i<siz; i++)
{
for(int j=0; j<siz; j++)
{
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for(int i=1; i<=tlen; i++)
{
if(T[i] == '*' &&i == 2) dp[i][0] = 1;
for(int j=1; j<=slen; j++)
{
//if(i == 0 && j == 0) continue;
if(T[i] == '.'){ dp[i][j] = dp[i-1][j-1];
// cout<<i<<" "<<j<<" --"<<dp[i][j]<<endl;
}
else if(T[i] != '*'){
if(T[i] == S[j]) dp[i][j] = dp[i-1][j-1];
//cout<<i<<" --"<<j<<" "<<dp[i][j]<<" "<<T[i]<<" "<<S[j]<<" "<<dp[i-1][j-1]<<endl;
}
else{
dp[i][j] = max(dp[i-2][j],dp[i-1][j]);
if(dp[i][j-1]&&S[j] == S[i - 1]) dp[i][j] = 1;
//cout<<i<<"--"<<j<<"--"<<dp[i][j]<<endl;
}
}
}
if(dp[tlen][slen] == 1)
{
cout<<"yes"<<endl;
}
else puts("no");
}
int main()
{
int t;
scanf("%d\n",&t);
while(t--)
{
scanf("%s",S+1);
scanf("%s",T+1);
S[0] = '#';
T[0] = '#';
solve();
}
return 0;
}