import java.io.*;
import java.util.*;
class Main {
static class BIT {
private final int size;
private final long[] tree;
public BIT(int size) {
this.size = size;
this.tree = new long[size + 1];
}
// Updates the value at index i by delta. (1-based index)
public void update(int i, long delta) {
for (; i <= size; i += i & -i) {
tree[i] += delta;
}
}
// Returns the cumulative sum from 1 to i. (1-based index)
public long query(int i) {
long sum = 0;
for (; i > 0; i -= i & -i) {
sum += tree[i];
}
return sum;
}
// Returns the sum from L to R inclusive.
public long queryRange(int L, int R) {
if (L > R) return 0;
return query(R) - query(L - 1);
}
}
static class Event {
int pa; // The coordinate to sweep over (P_a or P_a - A)
int pb; // The other coordinate (P_b or P_b - B + 1)
int type; // 0 for point addition, 1 for query
int id; // Original index k for points or r for queries
public Event(int pa, int pb, int type, int id) {
this.pa = pa;
this.pb = pb;
this.type = type;
this.id = id;
}
}
public static void main(String[] args) throws IOException {
FastScanner fs = new FastScanner();
int N = fs.nextInt();
int A = fs.nextInt();
int B = fs.nextInt();
String S = fs.next();
int[] Pa = new int[N + 1]; // Prefix count of 'a's (0-indexed P[0]=0, P[N]=total)
int[] Pb = new int[N + 1]; // Prefix count of 'b's
for (int i = 0; i < N; i++) {
Pa[i + 1] = Pa[i] + (S.charAt(i) == 'a' ? 1 : 0);
Pb[i + 1] = Pb[i] + (S.charAt(i) == 'b' ? 1 : 0);
}
List<Event> events = new ArrayList<>();
// Add point events (k = l-1, from 0 to N-1)
// We only care about points up to k=r-1, so k goes from 0 to N-1
for (int k = 0; k < N; k++) {
events.add(new Event(Pa[k], Pb[k], 0, k));
}
// Add query events (r from 1 to N)
// Query: P_a[k] <= P_a[r] - A (pa_max)
// P_b[k] >= P_b[r] - B + 1 (pb_min)
for (int r = 1; r <= N; r++) {
int pa_max = Pa[r] - A;
int pb_min = Pb[r] - B + 1;
// We only need to consider points where P_a[k] <= pa_max
// We sweep on P_a, so pa_max is the coordinate.
// P_b values are 0-indexed, so we can use them directly in BIT if we 1-index it.
events.add(new Event(pa_max, pb_min, 1, r));
}
// Sort events: Primary key P_a (ascending), Secondary key type (0 before 1), Tertiary key P_b (ascending)
events.sort((e1, e2) -> {
if (e1.pa != e2.pa) return Integer.compare(e1.pa, e2.pa);
if (e1.type != e2.type) return Integer.compare(e1.type, e2.type); // Process add points before queries
return Integer.compare(e1.pb, e2.pb);
});
// The maximum value for P_b is N. BIT size N+1 (0 to N).
// We use 1-based indexing for BIT, so the indices will be [1, N+1] for values [0, N].
BIT bit = new BIT(N + 1);
long totalPairs = 0;
for (Event event : events) {
if (event.type == 0) { // Add point (P_a[k], P_b[k])
// P_b values are 0-indexed, so add 1 for BIT index
bit.update(event.pb + 1, 1);
} else { // Query for (P_a[r]-A, P_b[r]-B+1)
// We are looking for P_b[k] >= P_b[r] - B + 1 (event.pb)
// The minimum P_b value for the range is event.pb.
// BIT stores count for P_b values: P_b[k] >= event.pb
// Max P_b is N (index N+1 in BIT). Min P_b in range is event.pb (index event.pb + 1 in BIT).
int pb_min_bit_index = event.pb + 1;
// Clamp pb_min_bit_index to 1 (min P_b value is 0)
pb_min_bit_index = Math.max(1, pb_min_bit_index);
// Clamp pb_min_bit_index to N+1 (max P_b value is N)
pb_min_bit_index = Math.min(N + 1, pb_min_bit_index);
// Count = total - count(P_b[k] < event.pb)
// P_b[k] < event.pb means P_b[k] <= event.pb - 1
// BIT index for P_b[k] <= event.pb - 1 is (event.pb - 1) + 1 = event.pb
int pb_max_negation_bit_index = event.pb;
// Clamp pb_max_negation_bit_index to N+1
pb_max_negation_bit_index = Math.min(N + 1, pb_max_negation_bit_index);
// Total count of points added so far
long totalPoints = bit.query(N + 1);
// Count of points with P_b[k] <= event.pb - 1
long negationCount = bit.query(pb_max_negation_bit_index);
long count = totalPoints - negationCount;
totalPairs += count;
}
}
System.out.println(totalPairs);
}
static class FastScanner {
BufferedReader br;
StringTokenizer st;
public FastScanner() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong() {
return Long.parseLong(next());
}
double nextDouble() {
return Double.parseDouble(next());
}
String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
}