[ 杂题 ] Codeforces923D Picking Strings

本文探讨了一种特定字符串转换规则下的转换逻辑,通过分析字符B、C、A的转换过程及限制条件,给出了验证两个字符串是否能相互转换的有效算法。文章详细介绍了如何利用字符串中特定字符的数量和位置关系来判断转换的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

瞎JB推一下,得到一些结论:

  • B→AC→AAB→AAAC→CB\rightarrow AC \rightarrow AAB \rightarrow AAAC \rightarrow CBACAABAAACC ,反过来也成立,得出 BBBCCC 是等价的,可以将所有 BBB 看成 CCC
  • C→AC→AAC→CC\rightarrow AC \rightarrow AAC \rightarrow CCACAACC ,也就是说 CCC 前面 AAA 的个数是可以随意改变的,那么只有末尾的 AAA 对答案有影响。
  • A→CCA\rightarrow CCACC ,那么 CCC 的个数不能减少,且只能增加 222 的倍数个。

假设 sssCCC 的个数为 aaa ,末尾 AAA 的个数为 bbbtttCCC 的个数为 ccc ,末尾 AAA 的个数为 ddd
由第 333 个结论得: aaaccc 必须满足 a≤ca\le cac(c−a) mod 2=0(c-a) ~mod ~2 =0(ca) mod 2=0
然后分类讨论。

  • a=ca=ca=c ,那么 CCC 的个数不能改变,只能把 bbb 减少 333 的倍数个。
  • a=0a=0a=0 ,那么只要判断是否满足 b>db>db>d,因为我们可以把一个 AAA 变成 CCCCCC ,再去掉前面所有 AAA ,使后面 AAA 的个数等于 ccc
  • 否则,只要判断是否满足 b≥db\ge dbd ,理由同上。

所有量都可以 O(n)O(n)O(n) 求,再分类讨论一下就好啦。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int k,n,m,Q;
int s1[N],s2[N],f1[N],f2[N];
int l1,r1,l2,r2;
char s[N],t[N];
bool Solve(int l1,int r1,int l2,int r2) {
	int x=s1[r1]-s1[l1-1],y=s2[r2]-s2[l2-1];
	if(x>y||((y-x)&1)) return 0;
	int len1=min(f1[r1],r1-l1+1),len2=min(f2[r2],r2-l2+1);
	if(x==y) {
		if(len1<len2) return 0;
		return !((len1-len2)%3);
	}
	if(!x) return len1>len2;
	return len1>=len2;
}
int main() {
	scanf("%s",s+1);n=strlen(s+1);
	scanf("%s",t+1);m=strlen(t+1);
	for(int i=1;i<=n;i++) s1[i]=s1[i-1]+(s[i]!='A'),f1[i]=s[i]=='A'?f1[i-1]+1:0;
	for(int i=1;i<=m;i++) s2[i]=s2[i-1]+(t[i]!='A'),f2[i]=t[i]=='A'?f2[i-1]+1:0;
	scanf("%d",&Q);
	while(Q--) {
		scanf("%d",&l1);scanf("%d",&r1);scanf("%d",&l2);scanf("%d",&r2);
		putchar(Solve(l1,r1,l2,r2)?'1':'0');
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值