[CF923D]Picking Strings
发布日期:2021-05-07 01:02:12 浏览次数:38 分类:原创文章

本文共 3575 字,大约阅读时间需要 11 分钟。

题目

题意概要
对于一个字符串,你可以进行任意次操作,每次选中一个子串,应用如下变换规则:

  • 如果该子串为 A A A ,将其用 B C BC BC 替换。
  • B → A C B\rightarrow AC BAC (此处为简写,下同)
  • C → A B C\rightarrow AB CAB
  • A A A → Ø AAA\rightarrow\text{\O} AAAØ (其中 Ø \text{\O} Ø 为空串)
  • 否则,该子串不发生任何变化。

给定两个字符串 S , T S,T S,T ,每次询问为 ⟨ S ′ , T ′ ⟩ \langle S',T'\rangle S,T ,分别是 S , T S,T S,T 的子串,输出 S ′ S' S 能否应用上方的变换得到 T ′ T' T

数据范围与约定
询问数量 q ≤ 1 0 5 q\le 10^5 q105 且字符串长度 ∣ S ∣ , ∣ T ∣ ≤ 1 0 5 |S|,|T|\le 10^5 S,T105

思路

借鉴了(尤其是特殊情况)。

注意下面的这一套组合技(用 A B C \Bbb{ABC} ABC 表示进行变换的子串):

B → A C → A A B → A A A C → C \Bbb B\rightarrow A\Bbb C\rightarrow AA\Bbb B\rightarrow \Bbb{AAA}C\rightarrow C BACAABAAACC

类似地,我们有 C → ⋯ → B C\rightarrow\cdots\rightarrow B CB

所以, C C C B B B 可以视作同一种字符

如果你不太理解,不妨这样思考:如果将 S S S 能够变成 T T T 视作 S S S 连向 T T T 的有向边,那么,对于两个字符串,如果其不匹配的地方均是 B , C B,C B,C 不匹配,那么二者在同一个强连通分量里。

现在重新审视变化规则,将 B , C B,C B,C 均视作 D D D ,得到

  • A → D D A\rightarrow DD ADD
  • D → A D D\rightarrow AD DAD
  • A A A → Ø AAA\rightarrow\text{\O} AAAØ

第二条告诉我们,在 D D D 前面可以随意地添加 A A A 字符。但是第三条又告诉我们,连在一起的 A A A 是可以被删除的。这告诉我们, D D D 前面的 A A A 的数量无足轻重

所以,我们想要表示一个字符串,可以用有序数对 ⟨ d , a ⟩ \langle d,a\rangle d,a 表示,其中 d d d 为字符串中 D D D 的数量,而 a a a 为最长的只包含 A A A 的后缀长度。

现在就有几个判断了。设 ⟨ D s , A s ⟩ \langle D_s,A_s\rangle Ds,As S S S 的数对表示法( T T T 类似)。

  1. 因为 A → D D A\rightarrow DD ADD 不会改变 D s D_s Ds 奇偶性(且只会越来越多),所以我们要求 D s ≤ D t ∧ 2 ∣ ( D t − D s ) D_s\le D_t\wedge 2|(D_t-D_s) DsDt2(DtDs)
    显然最后方的 A A A 是不可增加的。必须满足 A s ≥ A t A_s\ge A_t AsAt
  2. 比较糟糕的情况是,如果 D s = 0 ∧ D t ≠ 0 D_s=0\wedge D_t\ne 0 Ds=0Dt=0 ,你就不得不使用 A → D D A\rightarrow DD ADD 。但如果天不逢时,恰好 A s = A t A_s=A_t As=At(退无可退!),你就搞不定了。形式化地,何时一定不行: D s = 0 ∧ D t ≠ 0 ∧ A s = A t D_s=0\wedge D_t\ne 0\wedge A_s=A_t Ds=0Dt=0As=At
  3. 因为最后方的 A A A 无法增加,可以尝试三消,也就是说,如果满足这个条件就必定可行: 3 ∣ ( A s − A t ) 3|(A_s-A_t) 3(AsAt)
  4. 最后,你试着在最后截取一段 A t A_t At ,利用2.的判断,得到可行的条件 A s + 2 ≤ A t A_s+2\le A_t As+2At

注意这是有序的哦——前面的判断都无法确定时,才会使用该判断。

D s , A s D_s,A_s Ds,As 都是可以预处理 S S S 得到的。总复杂度 O ( ∣ S ∣ + ∣ T ∣ + q ) \mathcal O(|S|+|T|+q) O(S+T+q)

代码

#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cstring>using namespace std;inline long long readint(){   	long long a = 0; char c = getchar(), f = 1;	for(; c<'0' or c>'9'; c=getchar())		if(c == '-') f = -f;	for(; '0'<=c and c<='9'; c=getchar())		a = (a<<3)+(a<<1)+(c^48);	return a*f;}inline void writeint(long long x){   	if(x > 9) writeint(x/10);	putchar((x%10)^48);}# define MB template < class T >MB void getMax(T &a,const T &b){    if(a < b) a = b; }MB void getMin(T &a,const T &b){    if(b < a) a = b; }const int MaxN = 100005;char s[MaxN], t[MaxN];int cntS[MaxN], cntT[MaxN]; // D数量(前缀和)int laS[MaxN], laT[MaxN]; // 末尾连续的A长度int main(){   	// freopen("mine.txt","w",stdout);	scanf("%s %s",s,t);	int lens = strlen(s);	for(int i=1; i<=lens; ++i){   		cntS[i] = cntS[i-1];		if(s[i-1] == 'A')			laS[i] = laS[i-1]+1;		else laS[i] = 0, ++ cntS[i];	}	int lent = strlen(t);	for(int i=1; i<=lent; ++i){   		cntT[i] = cntT[i-1];		if(t[i-1] == 'A')			laT[i] = laT[i-1]+1;		else laT[i] = 0, ++ cntT[i];	}	int q = readint();	while(q --){   		int ls = readint()-1, rs = readint();		int lt = readint()-1, rt = readint(); // 左开右闭		int cnts = cntS[rs]-cntS[ls], cntt = cntT[rt]-cntT[lt];		int las = min(laS[rs],rs-ls), lat = min(laT[rt],rt-lt);		if(cnts > cntt or (cnts-cntt)%2 != 0 or las < lat)			putchar('0'); // 基本条件未达到		else if(cnts == 0 and cntt != 0 and las == lat)			putchar('0'); // 特殊情况:退无可退		else if((las-lat)%3 == 0 or 2+cnts <= cntt)			putchar('1'); // 在后面截一段lat		else putchar('0');	}	putchar('\n');	return 0;}
上一篇:vue指令之v-on
下一篇:vue指令之v-for

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2025年03月26日 21时53分45秒