Codeforces Round #541 (Div. 2) E. String Multiplication

問題

http://codeforces.com/contest/1131/problem/E

ある文字列 S と T が与えられた時、文字列 S の長さを m として S と T の積を  S \cdot T = T + S_1 + T + S_2 + ... + T + S_m + T と定義する。文字列 p1, p2, ..., pN が与えられるので  (...((p_1 \cdot p_2)\cdot p_3)...)\cdot p_N の中で同じ文字が連続して現れる回数の最大値を求めよ。

解法

pN 以外はぶつ切りにされてしまうが、 pN を構成する文字種が全て同じでとき、その文字を c とすると、  (...((p_1 \cdot p_2)\cdot p_3)...)\cdot p_N にの中で c が連続して現れる回数の最大値  C_N は、  C_N = (C_{N-1}+1)\times len(P_N) + C_{N-1} と表される。よって再帰的に求めていくことが出来る。

コード

use std::cmp;

fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { stdin: s.lock() };

    let n: usize = sc.read();
    let p: Vec<Vec<usize>> = (0..n)
        .map(|_| {
            sc.chars()
                .into_iter()
                .map(|c| c as usize - 'a' as usize)
                .collect()
        })
        .collect();

    let prefix_suffix: Vec<_> = p
        .iter()
        .map(|p| {
            let length = p.len();
            let head = p[0];
            let tail = p[length - 1];
            let prefix = p.iter().take_while(|&&c| c == head).count();
            let suffix = p.iter().rev().take_while(|&&c| c == tail).count();
            (head, tail, prefix, suffix)
        })
        .collect();

    let t = (0..n)
        .rev()
        .skip_while(|&i| {
            let (_, _, prefix, _) = prefix_suffix[i];
            prefix == p[i].len()
        })
        .next()
        .unwrap_or(0);

    let mut ans = vec![[0; 26]; n];
    for i in t..n {
        let (head, tail, prefix, suffix) = prefix_suffix[i];
        let length = p[i].len();

        if i == 0 {
            ans[i] = calc_longest(&p[i]);
        } else if i == t {
            assert!(prefix != length);
            let mut has = [false; 26];
            let mut max = calc_longest(&p[i]);
            for p in p[0..i].iter() {
                for &c in p.iter() {
                    has[c] = true;
                }
            }

            if head == tail && has[head] {
                update_max(&mut max[head], suffix + 1 + prefix);
            }
            if head != tail {
                if has[head] {
                    max[head] += 1;
                }
                if has[tail] {
                    max[tail] += 1;
                }
            }
            ans[i] = max;
        } else {
            let inner = ans[i - 1];
            let mut max = calc_longest(&p[i]);
            update_max(
                &mut max[head],
                cmp::min((inner[head] + 1) * length + inner[head], 1e9 as usize),
            );
            for i in 0..26 {
                if inner[i] > 0 {
                    update_max(&mut max[i], 1);
                }
            }
            ans[i] = max;
        }
    }

    println!("{}", ans[n - 1].iter().max().unwrap());
}

fn calc_longest(last: &Vec<usize>) -> [usize; 26] {
    let mut cur = 1;
    let n = last.len();
    let mut max = [0; 26];
    for i in 1..n {
        if last[i - cur] == last[i] {
            cur += 1;
        } else {
            update_max(&mut max[last[i - cur]], cur);
            cur = 1;
        }
    }
    update_max(&mut max[last[last.len() - 1]], cur);
    max
}

fn update_max<T: PartialOrd>(a: &mut T, b: T) {
    if *a < b {
        *a = b
    }
}

pub struct Scanner<R> {
    stdin: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .stdin
            .by_ref()
            .bytes()
            .map(|b| match b {
                Ok(b) => b,
                _ => panic!("{:?}", b),
            })
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r')
            .collect::<Vec<_>>();
        match unsafe { std::str::from_utf8_unchecked(&buf) }.parse() {
            Ok(r) => r,
            _ => panic!("Parse Error: {:?}", String::from_utf8(buf)),
        }
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}