ZROI 普专提 欢乐 ABC

Description

求字符串 S S 中有多少个子串,满足 A A B B C C 出现次数相等。

1 S 1 0 6 1 \leq |S| \leq 10^6

Solution

若有 A A B B C C 出现次数的前缀和。对于一个区间 [ l , r ] [l,r] ,若满足下述条件,则合法。

A r A l 1 = B r B l 1 A r B r = A l 1 B l 1 A_r - A_{l-1} = B_r - B_{l-1} \Longrightarrow A_r - B_r = A_{l-1}- B_{l-1}

B r B l 1 = C r C l 1 B r C r = B l 1 C l 1 B_r - B_{l-1} = C_r - C_{l-1} \Longrightarrow B_r - C_r = B_{l-1} - C_{l-1}

用 map 维护 ( A i B i ,   B i C i ) (A_i - B_i, \ B_i - C_i) 的二元组即可,注意 ( 0 , 0 ) (0,0) 应赋初值为 1 1

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
int read() {
	int x = 0, f = 0; char ch = 0;
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}
char s[N];
map < pair<int, int>, int> mp; 
int main(){
	scanf("%s", s);
	int n = strlen(s);
	int A = 0, B = 0, C = 0;
	ll ans = 0; 
	mp[make_pair(0, 0)] = 1;
	for (int i = 0; i < n; i++) {
		if (s[i] == 'A') A++;
		else if (s[i] == 'B') B++;
		else if (s[i] == 'C') C++;
		ans += mp[make_pair(A - B, B - C)]++;
	}
	printf("%lld\n", ans);
	return 0;
}
发布了28 篇原创文章 · 获赞 38 · 访问量 499

猜你喜欢

转载自blog.csdn.net/qq_39984146/article/details/104209556
ABC