Codeforces 923 D. Picking Strings
http://codeforces.com/contest/923/problem/D
题意:
A-->BC , B-->AC , C-->AB , AAA-->empty
问指定串S是否能变成目标串T
发现1:B与C等价
B-->AC-->AAB-->AAAC-->C
C-->AB-->AAC-->AAAB-->B
发现2:B前面的A可以消去
AB-->AAC-->AAAB-->A
新的变换:
A-->BB , B-->AB , AB-->A , AAA-->empty
所以:
结论1:B之前可以增删任意个A
结论2:在A的位置可以变成任意偶数个B
结合结论1和结论2,现在只剩下末尾的A待解决
末尾的A是无法增加的,所以只能考虑把S串末尾多余的A删去
综上所述,本题解法:
1、若S和T的 b的数量的奇偶性不同,则无解
因为B的改动只能是偶数个
2、若T中b的数量<S中b的数量,则无解
因为b只能加不能减
3、若T末尾A的数量>S末尾A的数量,则无解
因为末尾的A只能减不能加
删去末尾相同数量的A
考虑末尾的A
4、若 决定 变化最后1个A-->BB,在满足排除上面三种无解的前提下,若S中末尾A的数量>T中末尾B的数量 且 S中B的数量<T中B的数量,则有解
5、若决定删去3个A,若S串末尾A的数量是3的倍数 且 不存在 删去末尾相同数量的A后 S串是空串 T串不是空串
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100010; int sa[maxn],sb[maxn],ta[maxn],tb[maxn]; int n,m; char s[maxn],t[maxn]; int main() { scanf("%s%s",s+1,t+1); n=strlen(s+1);m=strlen(t+1); for(int i=1;i<=n;i++) { if(s[i]=='A')sa[i]=sa[i-1]+1; sb[i]=sb[i-1]+(s[i]=='B'||s[i]=='C'); } for(int i=1;i<=m;i++) { if(t[i]=='A')ta[i]=ta[i-1]+1; tb[i]=tb[i-1]+(t[i]=='B'||t[i]=='C'); } int Q; scanf("%d",&Q); int l,r,Sa,Sb,Ta,Tb,lenS,lenT; while(Q--) { scanf("%d%d",&l,&r); Sa=min(r-l+1,sa[r]); Sb=sb[r]-sb[l-1]; lenS=r-l+1; scanf("%d%d",&l,&r); Ta=min(r-l+1,ta[r]); Tb=tb[r]-tb[l-1]; lenT=r-l+1; if(Tb<Sb||((Tb&1)!=(Sb&1))||Ta>Sa) printf("0"); else if((Ta<Sa&&Tb>Sb)||(( Ta!=lenS || Ta==lenT) && (Sa-Ta)%3==0)) printf("1"); else printf("0"); } return 0; }