题意:给你一个串s和一个串t,然后有t次查询,每次查询输入四个数,问你第一个串中从x到y这一段能否通过操作变成第二个串的xx到yy这一段,具体有四种操作,每种操作次数和次序随意。
(1)A->BC (2)B->AC (3)C->AB (4)AAA->空串
题解:我们仔细分析一下这四种操作,首先根据2和3我们很容易发现B和C是等价的,可以相互转换,通过2,3,4这三种操作可以发现我们可以将所有B和C之前的A全部删掉或者剩余任意数量的A,然后根据1,2,3我们发现每一个B或者C都能产生多出来一个BC(因为BC等价,所以BC,CB我就统称为BC了),根据以上我们发现的信息来解决这道题。
首先我们对于两个串的子段,我们可以把其B,C之前的A全部去掉,但是要注意末尾的所有A不能删,因为删的话会多出来B或者C,剩下的我们列举出所有不能转化的情况即可。
以下为所有不能转化的情况:
1.第一个串的B和C的数量多于第二个串(B和C只会增多不会减小)
2.第一个串的B和C的数量比第二个串少奇数个(因为每个B或者C只能多产出个BC,也就是每次多偶数个)
3.第一个串末尾的A多于第二个串末尾的A(A只会减小不会增多)
4.两个串的B和C的数量相等,但是两串末尾A的数量差不是3的倍数(只有三个A能消成空串)
5.特判第一个串B和C数量是0的情况并且第而个串的B和C数量不是0个,因为此时这两个串的末尾A的个数就不能再相等了,不然就不能和转化了。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 100005
int sm1[maxn],sm2[maxn],sum1[maxn],sum2[maxn];
char s1[maxn],s2[maxn];
int main(void)
{
int T,x,y,xx,yy;
scanf("%s%s",s1+1,s2+1);
for(int i=1;s1[i]!='\0';i++)
{
if(s1[i]=='A')
sm1[i]=sm1[i-1]+1;
sum1[i]=sum1[i-1]+(s1[i]!='A');
}
for(int i=1;s2[i]!='\0';i++)
{
if(s2[i]=='A')
sm2[i]=sm2[i-1]+1;
sum2[i]=sum2[i-1]+(s2[i]!='A');
}
scanf("%d",&T);
while(T--)
{
int ans=1;
scanf("%d%d%d%d",&x,&y,&xx,&yy);
int x1=min(y-x+1,sm1[y]);
int x2=min(yy-xx+1,sm2[yy]);
int y1=sum1[y]-sum1[x-1];
int y2=sum2[yy]-sum2[xx-1];
if(y1>y2 || y1<y2 && (y1+y2)%2 || x1<x2)
ans=0;
if(y1==y2 && x1%3!=x2%3 || y1==0 && x1==x2 && y1!=y2)
ans=0;
printf("%d",ans);
}
printf("\n");
return 0;
}