
本文共 3575 字,大约阅读时间需要 11 分钟。
题目
题意概要
对于一个字符串,你可以进行任意次操作,每次选中一个子串,应用如下变换规则:
- 如果该子串为 A A A ,将其用 B C BC BC 替换。
- B → A C B\rightarrow AC B→AC (此处为简写,下同)
- C → A B C\rightarrow AB C→AB
- 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 q≤105 且字符串长度 ∣ S ∣ , ∣ T ∣ ≤ 1 0 5 |S|,|T|\le 10^5 ∣S∣,∣T∣≤105
思路
借鉴了(尤其是特殊情况
)。
注意下面的这一套组合技(用 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 B→AC→AAB→AAAC→C
类似地,我们有 C → ⋯ → B C\rightarrow\cdots\rightarrow B C→⋯→B 。
所以, 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 A→DD
- D → A D D\rightarrow AD D→AD
- 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 类似)。
- 因为 A → D D A\rightarrow DD A→DD 不会改变 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) Ds≤Dt∧2∣(Dt−Ds)
显然最后方的 A A A 是不可增加的。必须满足 A s ≥ A t A_s\ge A_t As≥At - 比较糟糕的情况是,如果 D s = 0 ∧ D t ≠ 0 D_s=0\wedge D_t\ne 0 Ds=0∧Dt=0 ,你就不得不使用 A → D D A\rightarrow DD A→DD 。但如果天不逢时,恰好 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=0∧Dt=0∧As=At
- 因为最后方的 A A A 无法增加,可以尝试三消,也就是说,如果满足这个条件就必定可行: 3 ∣ ( A s − A t ) 3|(A_s-A_t) 3∣(As−At)
- 最后,你试着在最后截取一段 A t A_t At ,利用
2.
的判断,得到可行的条件 A s + 2 ≤ A t A_s+2\le A_t As+2≤At
注意这是有序的哦——前面的判断都无法确定时,才会使用该判断。
而 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;}
发表评论
最新留言
关于作者
