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::cmp;
use std::collections::BTreeSet;

const BASE: u64 = 1e9 as u64 + 7;
const MOD: u64 = 1e9 as u64 + 9;

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

    let s: Vec<u8> = sc.chars().into_iter().map(|c| c as u8).collect();
    let t: Vec<u8> = sc.chars().into_iter().map(|c| c as u8).collect();
    let s_len = s.len();
    let m = t.len();
    let n = (m + s_len) * 2;
    let s = {
        let mut result = vec![0; n];
        let size = s.len();
        for i in 0..n {
            result[i] = s[i % size];
        }
        result
    };

    let s_hash = RollingHash::new(&s, BASE);
    let t_hash = RollingHash::new(&t, BASE);
    let mut prefix_set = BTreeSet::new();
    for i in 0..s_len {
        if s_hash.get_hash(i, i + m) == t_hash.get_hash(0, m) {
            prefix_set.insert(i);
        }
    }

    let mut length = 0;
    let mut used = BTreeSet::new();
    for &prefix in prefix_set.iter() {
        if used.contains(&prefix) {
            continue;
        }
        let mut current = BTreeSet::new();
        let mut cur = prefix;
        current.insert(cur);
        loop {
            if prefix_set.contains(&((cur + m) % s_len)) {
                cur = (cur + m) % s_len;
                if current.contains(&cur) {
                    println!("-1");
                    return;
                }
                current.insert(cur);
            } else {
                break;
            }
        }
        let mut cur = prefix;
        loop {
            if prefix_set.contains(&((cur + s_len - m) % s_len)) {
                cur = (cur + s_len - m) % s_len;
                if current.contains(&cur) {
                    println!("-1");
                    return;
                }
                current.insert(cur);
            } else {
                break;
            }
        }
        length = cmp::max(length, current.len());
        used.extend(current);
    }
    println!("{}", length);
}

pub struct RollingHash {
    hash: Vec<u64>,
    pow: Vec<u64>,
}

impl RollingHash {
    pub fn new(s: &[u8], base: u64) -> RollingHash {
        let n = s.len();
        let mut hash: Vec<u64> = vec![0; n + 1];
        let mut pow: Vec<u64> = vec![0; n + 1];
        pow[0] = 1;
        for i in 0..n {
            pow[i + 1] = (pow[i] * base) % MOD;
            hash[i + 1] = (hash[i] * base + (s[i] as u64)) % MOD;
        }
        RollingHash {
            hash: hash,
            pow: pow,
        }
    }

    /// Get hash of [l, r)
    pub fn get_hash(&self, l: usize, r: usize) -> u64 {
        (self.hash[r] + MOD - (self.hash[l] * self.pow[r - l]) % MOD) % MOD
    }
}

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| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    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()
    }
}