Problem:
Score : 400 points

Problem Statement

Snuke has N strings. The i-th string is s_i.

Let us concatenate these strings into one string after arranging them in some order.
Find the maximum possible number of occurrences of AB in the resulting string.

Constraints

1 \leq N \leq 10^{4}

2 \leq |s_i| \leq 10

s_i consists of uppercase English letters.

Input

Input is given from Standard Input in the following format:

N
s_1
\vdots
s_N

Output

Print the answer.

Sample Input 1

3
ABCA
XBAZ
BAD

Sample Output 1

2

For example, if we concatenate ABCA, BAD and XBAZ in this order, the resulting string ABCABADXBAZ has two occurrences of AB.

Sample Input 2

9
BEWPVCRWH
ZZNQYIJX
BAVREA
PA
HJMYITEOX
BCJHMRMNK
BP
QVFABZ
PRGKSPUNA

Sample Output 2

4

Sample Input 3

7
RABYBBE
JOZ
BMHQUVA
BPA
ISU
MCMABAOBHZ
SZMEHMA

Sample Output 3

4

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[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! {
        n: usize,
        s: [chars; n]
    };

    let mut to_a: Vec<Vec<char>> = vec![];
    let mut b_to_a: Vec<Vec<char>> = vec![];
    let mut b_to: Vec<Vec<char>> = vec![];
    let mut others: Vec<Vec<char>> = vec![];

    for i in 0..n {
        match (s[i][0], s[i][s[i].len() - 1]) {
            ('B', 'A') => b_to_a.push(s[i].clone()),
            (_, 'A') => to_a.push(s[i].clone()),
            ('B', _) => b_to.push(s[i].clone()),
            _ => others.push(s[i].clone())
        };
    }

    let mut maked: Vec<char> = vec![];
    if !to_a.is_empty() {
        vec_concat(&mut maked, &to_a.pop().unwrap());
    }
    for v in b_to_a {
        vec_concat(&mut maked, &v);
    }
    if !b_to.is_empty() {
        vec_concat(&mut maked, &b_to.pop().unwrap());
    }
    while !to_a.is_empty() && !b_to.is_empty() {
        vec_concat(&mut maked, &to_a.pop().unwrap());
        vec_concat(&mut maked, &b_to.pop().unwrap());
    }
    for v in b_to {
        vec_concat(&mut maked, &v);
    }
    for v in to_a {
        vec_concat(&mut maked, &v);
    }
    for v in others {
        vec_concat(&mut maked, &v);
    }

    let maked_u8 = maked.into_iter().map(|c| c as u8) .collect::<Vec<_>>();
    let key = "AB".bytes().collect::<Vec<_>>();
    println!("{}", search_rh(&maked_u8, &key).len());
}

fn vec_concat<T: Clone + std::fmt::Debug>(a: &mut Vec<T>, b: &Vec<T>) {
    for k in b {
        a.push(k.clone());
    }
}

#[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
}