【题目描述】
给定两个字符串s,t,其中s只包含小写字母以及*,t只包含小写字母。你可以进行任意多次操作,每次选择s中的一个*,将它修改为任意多个(可以是0个)它的前一个字符,问能否将s修改为t。
【输入格式】
第一行一个整数T表示数据组数。
每组数据两行,第一行一个字符串s,第二行一个字符串t。
【输出格式】
每组数据输出一行,如果能将s修改为t,输出Yes,否则输出No。
【输入样例】
2
a*
aaaa
a*
ab
【输出样例】
Yes
No
【备注】
数据规模:
对于20%的数据,|s|,|t|<=7。
对于60%的数据,|s|,|t|<=300。
对于100%的数据,T<=100,|s|,|t|<=30000。
对于20%的数据,可以发现多个*连在一起与1个*效果等价,所以只需枚举每个*将上一个字母复制了多少遍。
对于60%的数据,用f[i][j]表示s[1..i]能否变为t[1..t],如果s[i]不是*则f[i][j]=f[i-1][j-1],否则f[i][j]=max{f[i-1][k]},其中t[k+1]..t[j]=s[i-1],复杂度(T|s||t|)
对于100%的数据,用lens指向s,lent指向t,将每一段相同字母分离出来比较,如果s字符个数大于t字符个数,那么为非法情况,如果s少于t且s这段中无*,那么同样非法,其他情况均合法,复杂度(T|s|+|t|)
贴代码:
#include<bits/stdc++.h>
using namespace std;
char s[30001],t[30001];
int len1,len2,ids,idt;
bool cmp(char c)
{
int cnts=0,cntt=0;
bool flag=false;
while(s[ids]==c||s[ids]=='*')
{
if(s[ids]==c)
cnts++;
if(s[ids]=='*')
flag=true;
ids++;
}
while(t[idt]==c)
idt++,cntt++;
if(cnts>cntt)
return false;
if(cnts<cntt&&!flag)
return false;
return true;
}
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
scanf("%s",s);
scanf("%s",t);
len1=strlen(s),len2=strlen(t);
ids=0,idt=0;
char r;
if(s[0]==t[0])
r=t[0];
else
{
puts("No");
continue;
}
bool flag=true,flag1=false;
while(flag&&(ids<len1&&idt<len2))
{
flag=cmp(r);
if(s[ids]==t[idt])
r=s[ids];
else
{
puts("No");
flag1=true;
break;
}
}
if(!flag1)
{
if(!flag)
puts("No");
else
puts("Yes");
}
}
return 0;
}