Problem:
Ambiguous Encoding

A friend of yours is designing an encoding scheme of a set of characters into a set of variable length bit sequences. You are asked to check whether the encoding is ambiguous or not. In an encoding scheme, characters are given distinct bit sequences of possibly different lengths as their codes. A character sequence is encoded into a bit sequence which is the concatenation of the codes of the characters in the string in the order of their appearances. An encoding scheme is said to be ambiguous if there exist two different character sequences encoded into exactly the same bit sequence. Such a bit sequence is called an “ambiguous binary sequence”.

For example, encoding characters “A”, “B”, and “C” to 0, 01 and 10, respectively, is ambiguous. This scheme encodes two different character strings “AC” and “BA” into the same bit sequence 010.

Input

The input consists of a single test case of the following format.

$n$
$w_1$
.
.
.
$w_n$

Here, $n$ is the size of the set of characters to encode ($1 \leq n \leq 1000$). The $i$-th line of the following $n$ lines, $w_i$, gives the bit sequence for the $i$-th character as a non-empty sequence of at most 16 binary digits, 0 or 1. Note that different characters are given different codes, that is, $w_i \ne w_j$ for $i \ne j$.

Output

If the given encoding is ambiguous, print in a line the number of bits in the shortest ambiguous binary sequence. Output zero, otherwise.

Sample Input 1

3
0
01
10

Sample Output 1

3

Sample Input 2

3
00
01
1

Sample Output 2

0

Sample Input 3

3
00
10
1

Sample Output 3

0

Sample Input 4

10
1001
1011
01000
00011
01011
1010
00100
10011
11110
0110

Sample Output 4

13

Sample Input 5

3
1101
1
10

Sample Output 5

4

Solution in Rust (judge verdict: Accepted)

#![allow(unused_imports, unused_macros, non_snake_case)]
use std::cmp::{max, min, Ordering};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};

//{{{ macros missing in 1.15.1
#[macro_use]
mod macros {
    macro_rules! eprint {
        ($($t:tt)*) => {{
            use ::std::io::Write;
            let _ = write!(::std::io::stderr(), $($t)*);
        }};
    }
    macro_rules! eprintln {
        () => { eprintln!(""); };
        ($($t:tt)*) => {{
            use ::std::io::Write;
            let _ = writeln!(::std::io::stderr(), $($t)*);
        }};
    }
    macro_rules! dbg {
        ($val:expr) => {
            match $val {
                tmp => {
                    eprintln!(
                        "[{}:{}] {} = {:#?}",
                        file!(),
                        line!(),
                        stringify!($val),
                        &tmp
                    );
                    tmp
                }
            }
        };
    }
}
//}}}

#[derive(Eq, PartialEq, Ord, PartialOrd, Debug)]
struct State {
    cost: usize,
    line: usize,
    index: usize,
}

#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)]
pub struct Reverse<T>(pub T);

impl<T: PartialOrd> PartialOrd for Reverse<T> {
    #[inline]
    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }

    #[inline]
    fn lt(&self, other: &Self) -> bool {
        other.0 < self.0
    }
    #[inline]
    fn le(&self, other: &Self) -> bool {
        other.0 <= self.0
    }
    #[inline]
    fn ge(&self, other: &Self) -> bool {
        other.0 >= self.0
    }
    #[inline]
    fn gt(&self, other: &Self) -> bool {
        other.0 > self.0
    }
}

impl<T: Ord> Ord for Reverse<T> {
    #[inline]
    fn cmp(&self, other: &Reverse<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}

fn run() {
    let stdin = std::io::stdin();
    let mut sc = Scanner::new(stdin.lock());
    let n: usize = sc.read();
    let mut w: Vec<Vec<char>> = Vec::new();
    for _ in 0..n {
        let s = sc.read_chars();
        w.push(s);
    }

    let mut queue = BinaryHeap::new();
    let mut min_cost = HashMap::new();
    for i in 0..n {
        queue.push(Reverse(State {
            cost: 0,
            line: i,
            index: 0,
        }));
        min_cost.insert((i, 0), 0);
    }

    let mut answer = None;
    while let Some(Reverse(s)) = queue.pop() {
        let min_c = min_cost[&(s.line, s.index)];
        if min_c < s.cost {
            continue;
        }
        let rest_len = w[s.line].len() - s.index;
        if rest_len == 0 {
            answer = Some(s.cost);
            break;
        }
        for i in 0..n {
            if i == s.line && s.index == 0 {
                continue;
            }
            let check_len = min(rest_len, w[i].len());
            let ok = (0..check_len).all(|j| w[i][j] == w[s.line][s.index + j]);
            if !ok {
                continue;
            }
            let state = if check_len < rest_len {
                State {
                    line: s.line,
                    index: s.index + check_len,
                    cost: s.cost + check_len,
                }
            } else {
                State {
                    line: i,
                    index: check_len,
                    cost: s.cost + check_len,
                }
            };
            if *min_cost
                .get(&(state.line, state.index))
                .unwrap_or(&usize::max_value())
                > state.cost
            {
                /*
                eprintln!("{:?} -> {:?}", s, state);
                eprintln!("i: {}", i);
                eprintln!("check_len: {}", check_len);
                eprintln!("rest_len: {}", rest_len);
                */
                min_cost.insert((state.line, state.index), state.cost);
                queue.push(Reverse(state));
            }
        }
    }
    println!("{}", answer.unwrap_or(0));
}

fn main() {
    std::thread::Builder::new()
        .name("run".to_string())
        .stack_size(1024 * 1024 * 1024)
        .spawn(run)
        .unwrap()
        .join()
        .unwrap()
}

//{{{ Scanner
pub struct Scanner<R> {
    reader: R,
}

impl<R> Scanner<R> {
    pub fn new(r: R) -> Scanner<R> {
        Scanner { reader: r }
    }
}

fn is_whitespace(b: u8) -> bool {
    b == b' ' || b == b'\n' || b == b'\r' || b == b'\t'
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        let buf = std::io::Read::bytes(self.reader.by_ref())
            .map(|b| b.expect("Read failed"))
            .skip_while(|&b| is_whitespace(b))
            .take_while(|&b| !is_whitespace(b))
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error")
    }

    pub fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }

    pub fn read_chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}
//}}}