一个与标答不同的想法
首先,根据观察可知:如果我们从前往后匹配,当前匹配上了
s
s
s 的第
i
i
i个字符,那么下一个能匹配的一定是与当前位置
i
i
i的奇偶性不同的位置。
然后我们就分奇偶建立序列自动机,然后从头开始时枚举是从奇数位置开始还是偶数位置。然后按一般的序列自动机匹配方式双指针扫就可以了。
普遍的坑点(fst点)在于即使匹配上了,
s
s
s剩下的字符个数也需要是偶数个,否则就不行(末尾字符都要删)。
然后是这种做法的正确性证明:
考虑两个奇偶性相同且字符相同的位置
i
,
j
(
i
<
j
)
:
j
所
能
跳
转
的
位
置
,
i
都
能
跳
转
,
显
然
选
择
i
更
优
。
i,j(i<j):j所能跳转的位置,i都能跳转,显然选择i更优。
i,j(i<j):j所能跳转的位置,i都能跳转,显然选择i更优。
有
关
结
尾
时
判
断
s
剩
余
字
符
的
问
题
:
有关结尾时判断s剩余字符的问题:
有关结尾时判断s剩余字符的问题:
由
于
t
是
确
定
的
串
,
所
以
s
当
前
位
置
的
奇
偶
性
变
换
的
次
数
是
固
定
的
。
由于t是确定的串,所以s当前位置的奇偶性变换的次数是固定的。
由于t是确定的串,所以s当前位置的奇偶性变换的次数是固定的。
这
样
的
话
,
贪
心
选
择
靠
前
的
位
置
匹
配
,
也
不
会
影
响
最
终
判
断
s
剩
余
字
符
的
奇
偶
性
这样的话,贪心选择靠前的位置匹配,也不会影响最终判断s剩余字符的奇偶性
这样的话,贪心选择靠前的位置匹配,也不会影响最终判断s剩余字符的奇偶性
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int T,ch[maxn][26],st[2][26];
char s[maxn],t[maxn];
signed main(int argc,char* argv[]){
//freopen("d.in","r",stdin);
//freopen("d.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cin>>(s+1);
cin>>(t+1);
int n=strlen(s+1),m=strlen(t+1);
for(int i=0;i<2;i++)memset(st[i],0,sizeof(st[i]));
for(int i=0;i<=n;i++)memset(ch[i],0,sizeof(ch[i]));
if(m>n){printf("NO\n");continue;}
for(int i=n-1;i>=0;i--){
if(i&1){
for(int j=0;j<26;j++)ch[i][j]=st[0][j];
ch[i][s[i+1]-'a']=i+1;
st[0][s[i+1]-'a']=i+1;
}
else{
for(int j=0;j<26;j++)ch[i][j]=st[1][j];
ch[i][s[i+1]-'a']=i+1;
st[1][s[i+1]-'a']=i+1;
}
}
for(int i=0;i<26;i++){ch[0][i]=st[0][i];
}
int v=1,i=0,ans=0;
while(i<n){
if(ch[i][t[v]-'a']){
i=ch[i][t[v]-'a'];v++;
}
else{
break;
}
if(v>m){if((n-i+1)&1)ans=1;break;}
}
if(ans){printf("YES\n");continue;}
for(int i=0;i<26;i++){ch[0][i]=st[1][i];
}
v=1,i=0,ans=0;
while(i<n){
if(ch[i][t[v]-'a']){
i=ch[i][t[v]-'a'];v++;
}
else{
break;
}
if(v>m){if((n-i+1)&1)ans=1;break;}
}
if(ans){printf("YES\n");continue;}
else printf("NO\n");
}
}