Problem:
Score : 600 points

Problem Statement

You are given a string s consisting of A, B and C.

Snuke wants to perform the following operation on s as many times as possible:

Choose a contiguous substring of s that reads ABC and replace it with BCA.

Find the maximum possible number of operations.

Constraints

1 \leq |s| \leq 200000

Each character of s is A, B and C.

Input

Input is given from Standard Input in the following format:

s

Output

Find the maximum possible number of operations.

Sample Input 1

ABCABC

Sample Output 1

3

You can perform the operations three times as follows: ABCABC → BCAABC → BCABCA → BCBCAA. This is the maximum result.

Sample Input 2

C

Sample Output 2

0

Sample Input 3

ABCACCBABCBCAABCB

Sample Output 3

6

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

#[allow(unused_macros)]
macro_rules! input {
    ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; let mut next = || { iter . next ( ) . unwrap ( ) } ; input_inner ! { next , $ ( $ r ) * } };
    ( $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let mut bytes = std :: io :: Read :: bytes ( std :: io :: BufReader :: new ( stdin . lock ( ) ) ) ; let mut next = move || -> String { bytes . by_ref ( ) . map ( | r | r . unwrap ( ) as char ) . skip_while ( | c | c . is_whitespace ( ) ) . take_while ( | c |! c . is_whitespace ( ) ) . collect ( ) } ; input_inner ! { next , $ ( $ r ) * } };
}
#[allow(unused_macros)]
macro_rules! input_inner {
    ( $ next : expr ) => { };
    ( $ next : expr , ) => { };
    ( $ next : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ next , $ t ) ; input_inner ! { $ next $ ( $ r ) * } };
}
#[allow(unused_macros)]
macro_rules! read_value {
    ( $ next : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ next , $ t ) ) ,* ) };
    ( $ next : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ next , $ t ) ) . collect ::< Vec < _ >> ( ) };
    ( $ next : expr , chars ) => { read_value ! ( $ next , String ) . chars ( ) . collect ::< Vec < char >> ( ) };
    ( $ next : expr , usize1 ) => { read_value ! ( $ next , usize ) - 1 };
    ( $ next : expr , $ t : ty ) => { $ next ( ) . parse ::<$ t > ( ) . expect ( "Parse error" ) };
}

fn main() {
    input! {
        s: chars
    }
    let s8 = s.iter().map(|&c| c as u8) .collect::<Vec<_>>();
    let indices = search_rh(&s8, "ABC".as_bytes());
    let mut sm = s;
    let mut deque = indices .into_iter().collect::<std::collections::VecDeque<_>>();
    let mut ret = 0u64;
    while let Some(i) = deque.pop_back() {
        if is_abc(&sm, i) {
            ret += 1;
            sm[i] = 'B';
            sm[i+1] = 'C';
            sm[i+2] = 'A';
            if i>=1 && sm[i-1] == 'A' {
                deque.push_front(i-1);
            }
            let j = i+2;
            if is_abc(&sm, j) || is_abc(&sm, j+1) {
                deque.push_front(j);
            }
        }
    }
    println!("{}" ,ret);
}

fn is_abc(s: &[char], i: usize) -> bool {
    i+2 < s.len() && s[i] == 'A' && s[i+1] == 'B' && s[i+2] == 'C'
}

#[doc = " O(len(base) + len(key))"]
#[allow(dead_code)]
pub fn search_rh<T: Into<u64> + std::clone::Clone>(base: &[T], key: &[T]) -> Vec<usize> {
    use std::num::Wrapping;
    const B: Wrapping<u64> = Wrapping(1_000_000_007u64);
    let key_len = key.len();
    let base_len = base.len();
    if key_len > base_len {
        return vec![];
    }
    let mut t = Wrapping(1u64);
    for _ in 0..key_len {
        t *= B;
    }
    let mut key_h = Wrapping(0u64);
    let mut base_h = Wrapping(0u64);
    for i in 0..key_len {
        key_h = key_h * B + Wrapping(key[i].clone().into());
        base_h = base_h * B + Wrapping(base[i].clone().into());
    }
    let mut ret = vec![];
    for i in (0..).take_while(|&i| i + key_len <= base_len) {
        if key_h == base_h {
            ret.push(i);
        }
        if i + key_len < base_len {
            base_h = base_h * B + Wrapping(base[i + key_len].clone().into())
                - Wrapping(base[i].clone().into()) * t;
        }
    }
    ret
}