459. 重复的子字符串

题目描述

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

解题思路

例子

abcabcabcabc
000123456789

abaaba
001123

abacabacabac
001012345678

abac
0010

abcabc
000123
#![allow(unused)]

fn main() {
struct Solution {}

impl Solution {
    pub fn repeated_substring_pattern(s: String) -> bool {
        let n = s.len();
        let mut next = vec![0; n];
        let s = s.chars().collect::<Vec<char>>();
        let mut j = 0;
        for i in 1..n {
            while j >= 1 && s[i] != s[j] {
                j = next[j - 1];
            }
            if s[i] == s[j] {
                j += 1;
            }
            next[i] = j;    // next 表示以i结尾的字符串最大前后缀长度
        }
        let a = *next.last().unwrap();
        if a == 0 { return false }
        let b = n - a;
        if n % b != 0 { return false }
        else { true }
    }
}

}

学习感想

什么时候该用KMP很懵

next 数组 -- 前缀表 内容是什么??next[i] 记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀

前缀表是用来回退的,它记录了模式串P与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。

记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。

记住例子

abcdabcd
00001234
#![allow(unused)]
fn main() {
struct Solution {}

impl Solution {
    pub fn repeated_substring_pattern(s: String) -> bool {
        let s: Vec<u8> = s.bytes().collect();
        // next[i] -> max length of common prefix & suffix of string s[0..=i]
        let mut next: Vec<usize> = vec![0usize; s.len()];
        let mut left: usize = 0usize;   // the current max length of common pre/suf-fix
        for right in 1usize .. next.len() { // calculate each next[right]
            while left > 1usize && s[right] != s[left] {
                left = next[left - 1usize];
            }
            if s[right] == s[left] {
                left += 1usize;
            }
            next[right] = left;
        }
        let x: usize = s.len() - *next.last().unwrap();
        match s.len() % x {
            0 => true,
            _ => false,
        }
    }
}
}