Problem:
Score : 600 points

Problem Statement

Given are two strings s and t consisting of lowercase English letters. Determine if the number of non-negative integers i satisfying the following condition is finite, and find the maximum value of such i if the number is finite.

There exists a non-negative integer j such that the concatenation of i copies of t is a substring of the concatenation of j copies of s.

Notes

A string a is a substring of another string b if and only if there exists an integer x (0 \leq x \leq |b| - |a|) such that, for any y (1 \leq y \leq |a|), a_y = b_{x+y} holds.

We assume that the concatenation of zero copies of any string is the empty string. From the definition above, the empty string is a substring of any string. Thus, for any two strings s and t, i = 0 satisfies the condition in the problem statement.

Constraints

1 \leq |s| \leq 5 \times 10^5

1 \leq |t| \leq 5 \times 10^5

s and t consist of lowercase English letters.

Input

Input is given from Standard Input in the following format:

s
t

Output

If the number of non-negative integers i satisfying the following condition is finite, print the maximum value of such i; if the number is infinite, print -1.

Sample Input 1

abcabab
ab

Sample Output 1

3

The concatenation of three copies of t, ababab, is a substring of the concatenation of two copies of s, abcabababcabab, so i = 3 satisfies the condition.

On the other hand, the concatenation of four copies of t, abababab, is not a substring of the concatenation of any number of copies of s, so i = 4 does not satisfy the condition.

Similarly, any integer greater than 4 does not satisfy the condition, either. Thus, the number of non-negative integers i satisfying the condition is finite, and the maximum value of such i is 3.

Sample Input 2

aa
aaaaaaa

Sample Output 2

-1

For any non-negative integer i, the concatenation of i copies of t is a substring of the concatenation of 4i copies of s. Thus, there are infinitely many non-negative integers i that satisfy the condition.

Sample Input 3

aba
baaab

Sample Output 3

0

As stated in Notes, i = 0 always satisfies the condition.

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

use std::io::prelude::*;

fn input<T: std::str::FromStr>() -> T {
    let stdin = std::io::stdin();
    let token: String = stdin
        .lock()
        .bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().unwrap()
}

fn main() {
    let s: String = input();
    let t: String = input();

    let slen = s.len();
    let tlen = t.len();

    let rt = RollingHashString::from_str(&t);
    let mut rs = RollingHashString::new();
    while rs.len() < slen + tlen {
        rs.push_str(&s);
    }

    let mut succ = vec![slen; slen];
    let mut pred = vec![0; slen];
    for i in 0..slen {
        if rs.substr(i, tlen) == rt {
            let j = (i + tlen) % slen;
            succ[i] = j;
            pred[j] += 1;
        }
    }

    let mut dist = vec![-1; slen];
    let mut q = std::collections::VecDeque::new();
    for i in 0..slen {
        if pred[i] == 0 {
            dist[i] = 0;
            q.push_back(i);
        }
    }
    while let Some(i) = q.pop_front() {
        if succ[i] == slen {
            continue;
        }
        let j = succ[i];
        pred[j] -= 1;
        dist[j] = dist[i] + 1;
        if pred[j] == 0 {
            q.push_back(j);
        }
    }

    let mut ok = true;
    let mut ans = 0;
    for i in 0..slen {
        if dist[i] < 0 {
            ok = false;
            break;
        }
        ans = std::cmp::max(ans, dist[i]);
    }

    println!("{}", if ok { ans } else { -1 });
}

struct RollingHashString {
    inner: String,
    hasher: Box<[RollingHasher]>,
}

struct RollingHashSubstring<'a> {
    inner: &'a str,
    hash: Box<[u64]>,
}

impl RollingHashString {
    fn hasher() -> Box<[RollingHasher]> {
        Box::new([
            RollingHasher::new(997, 999999937),
            RollingHasher::new(1000003, 1000000007),
            RollingHasher::new(100000007, 1000000009),
        ])
    }

    fn new() -> RollingHashString {
        RollingHashString {
            inner: String::new(),
            hasher: RollingHashString::hasher(),
        }
    }

    fn from_str(string: &str) -> RollingHashString {
        let mut rs = RollingHashString::new();
        rs.push_str(string);
        rs
    }

    fn push_str(&mut self, string: &str) {
        self.inner.push_str(string);
        for h in self.hasher.iter_mut() {
            std::hash::Hasher::write(h, string.as_bytes());
        }
    }

    fn substr<'a>(&'a self, start: usize, length: usize) -> RollingHashSubstring<'a> {
        RollingHashSubstring {
            inner: &self.inner[start..start + length],
            hash: self
                .hasher
                .iter()
                .map(|h| h.make_hash(start, length))
                .collect::<Vec<_>>()
                .into_boxed_slice(),
        }
    }
}

impl std::fmt::Display for RollingHashString {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.inner.fmt(f)
    }
}

impl<'a> std::fmt::Display for RollingHashSubstring<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.inner.fmt(f)
    }
}

impl std::ops::Deref for RollingHashString {
    type Target = str;

    fn deref(&self) -> &str {
        &self.inner
    }
}

impl<'a> std::ops::Deref for RollingHashSubstring<'a> {
    type Target = str;

    fn deref(&self) -> &str {
        self.inner
    }
}

impl PartialEq for RollingHashString {
    fn eq(&self, other: &RollingHashString) -> bool {
        self.substr(0, self.len()).hash == other.substr(0, other.len()).hash
    }
}

impl<'a> PartialEq<RollingHashSubstring<'a>> for RollingHashString {
    fn eq(&self, other: &RollingHashSubstring<'a>) -> bool {
        self.substr(0, self.len()).hash == other.hash
    }
}

impl<'a> PartialEq<RollingHashString> for RollingHashSubstring<'a> {
    fn eq(&self, other: &RollingHashString) -> bool {
        self.hash == other.substr(0, other.len()).hash
    }
}

impl<'a> PartialEq for RollingHashSubstring<'a> {
    fn eq(&self, other: &RollingHashSubstring<'a>) -> bool {
        self.hash == other.hash
    }
}

impl Eq for RollingHashString {}
impl<'a> Eq for RollingHashSubstring<'a> {}

struct RollingHasher {
    radix: u64,
    modulus: u64,
    hash: Vec<u64>,
    pow: Vec<u64>,
}

impl RollingHasher {
    fn new(radix: u64, modulus: u64) -> RollingHasher {
        RollingHasher {
            radix: radix,
            modulus: modulus,
            hash: vec![0],
            pow: vec![1],
        }
    }

    fn make_hash(&self, start: usize, length: usize) -> u64 {
        let mut h = self.hash[start + length] + self.modulus
            - self.hash[start] * self.pow[length] % self.modulus;
        if h > self.modulus {
            h -= self.modulus;
        }
        h
    }
}

impl std::hash::Hasher for RollingHasher {
    fn finish(&self) -> u64 {
        self.hash[self.hash.len() - 1]
    }

    fn write(&mut self, bytes: &[u8]) {
        let n = self.hash.len();
        self.hash.resize(n + bytes.len(), 0);
        self.pow.resize(n + bytes.len(), 0);
        for i in 0..bytes.len() {
            self.hash[n + i] = (self.hash[n + i - 1] * self.radix + bytes[i] as u64) % self.modulus;
            self.pow[n + i] = self.pow[n + i - 1] * self.radix % self.modulus;
        }
    }
}