Problem:
Score : 700 points

Problem Statement

You are given a string S consisting of a,b and c. Find the number of strings that can be possibly obtained by repeatedly performing the following operation zero or more times, modulo 998244353:

Choose an integer i such that 1\leq i\leq |S|-1 and the i-th and (i+1)-th characters in S are different. Replace each of the i-th and (i+1)-th characters in S with the character that differs from both of them (among a, b and c).

Constraints

2 \leq |S| \leq 2 × 10^5

S consists of a, b and c.

Input

Input is given from Standard Input in the following format:

S

Output

Print the number of strings that can be possibly obtained by repeatedly performing the operation, modulo 998244353.

Sample Input 1

abc

Sample Output 1

3

abc, aaa and ccc can be obtained.

Sample Input 2

abbac

Sample Output 2

65

Sample Input 3

babacabac

Sample Output 3

6310

Sample Input 4

ababacbcacbacacbcbbcbbacbaccacbacbacba

Sample Output 4

148010497

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

use std::io::*;
use std::str::FromStr;
use std::collections::HashSet;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
fn pow_mod(base: i64, power: i64, modulo: i64) -> i64 {
    let mut base = base;
    let mut power = power;
    let mut ans = 1;
    while power > 0 {
        if power & 1 == 1 {
            ans = ans * base % modulo;
        }
        power >>= 1;
        base = base * base % modulo;
    }
    ans
}

const MOD: i64 = 998244353;
struct Solver {
    s: Vec<usize>,
}

impl Solver {
    fn new() -> Solver {
        let s = read::<String>()
            .chars()
            .map(|v| v as usize - 'a' as usize)
            .collect::<Vec<usize>>();
        Solver { s: s }
    }
    fn solve(&mut self) -> i64 {
        let n = self.s.len();
        let mut ans = 0;
        if n < 6 {
            let mut visit = HashSet::<Vec<usize>>::new();
            let mut que = vec![self.s.clone()];
            visit.insert(self.s.clone());
            while let Some(s) = que.pop() {
                for i in 0..n - 1 {
                    if s[i] != s[i + 1] {
                        let mut ns = s.clone();
                        let nc = match s[i] + s[i + 1] {
                            1 => 2,
                            2 => 1,
                            3 => 0,
                            _ => 9999,
                        };
                        ns[i] = nc;
                        ns[i + 1] = nc;
                        if visit.contains(&ns) {
                            continue;
                        }
                        visit.insert(ns.clone());
                        que.push(ns);
                    }
                }
            }
            return visit.len() as i64;
        }
        let mut cnts = vec![0, 0, 0];
        let mut cont_seq = false;
        for i in 0..n {
            cnts[self.s[i]] += 1;
            if i != n - 1 && self.s[i] == self.s[i + 1] {
                cont_seq = true;
            }
        }
        if cnts[0] == n || cnts[1] == n || cnts[2] == n {
            return 1;
        }
        if !cont_seq {
            ans += 1;
        }
        ans = (ans + pow_mod(3, n as i64 - 1, MOD)) % MOD;
        ans = (ans - pow_mod(2, n as i64 - 1, MOD) + MOD) % MOD;
        if n % 3 == 0 {
            cnts[0] %= 3;
            cnts[1] %= 3;
            cnts[2] %= 3;
            cnts.sort();
            if cnts[0] == 0 && cnts[1] == 1 {
                ans = (ans + pow_mod(2, n as i64 / 3 - 1, MOD)) % MOD;
            } else {
                ans = (ans - pow_mod(2, n as i64 / 3, MOD) + MOD) % MOD;
            }
        }
        ans
    }
}

fn main() {
    let mut solver = Solver::new();
    let ans = solver.solve();
    println!("{}", ans);
}