LeetCode每日一题(1316. Distinct Echo Substrings)

该博客介绍了如何利用Rabin-Karp算法解决LeetCode中的1316题,即找到文本中所有可以表示为自身拼接的不重复非空子字符串。例如,输入""abcabcabc""时,输出3,因为有""abcabc"

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Return the number of distinct non-empty substrings of text that can be written as the concatenation of some string with itself (i.e. it can be written as a + a where a is some string).

Example 1:

Input: text = “abcabcabc”
Output: 3

Explanation: The 3 substrings are “abcabc”, “bcabca” and “cabcab”.

Example 2:

Input: text = “leetcodeleetcode”
Output: 2

Explanation: The 2 substrings are “ee” and “leetcodeleetcode”.

Constraints:

  • 1 <= text.length <= 2000
  • text has only lowercase English letters.

这题的关键是 Rabin-Karp 算法来找相邻的重复子字符串, 关于 Rabin-Karp 算法,大家自己去查吧,我也只是现学现用, 理解不多就不班门弄斧了。


use std::collections::HashSet;

impl Solution {
    const M: i64 = 10i64.pow(9) + 7;
    const P: i64 = 31;
    fn hash(chars: &Vec<char>, len: usize) -> i32 {
        let mut d = 1;
        for _ in 1..len {
            d *= Solution::P;
            d %= Solution::M;
        }
        let mut ans = 0;
        let mut left = Vec::new();
        let mut right = Vec::new();
        let mut left_hash = 0;
        let mut right_hash = 0;
        let mut chars = chars.clone();
        let mut set = HashSet::new();
        while !chars.is_empty() {
            right.push(chars.remove(0));
            if right.len() > len {
                let c = right.remove(0);
                right_hash += Solution::M;
                right_hash -= d * c as i64 % Solution::M;
                right_hash %= Solution::M;
                left.push(c);
            }
            right_hash *= Solution::P;
            right_hash %= Solution::M;
            right_hash += *right.last().unwrap() as i64;
            right_hash %= Solution::M;
            if left.len() > len {
                let c = left.remove(0);
                left_hash += Solution::M;
                left_hash -= d * c as i64 % Solution::M;
                left_hash %= Solution::M;
            }
            if !left.is_empty() {
                left_hash *= Solution::P;
                left_hash %= Solution::M;
                left_hash += *left.last().unwrap() as i64;
                left_hash %= Solution::M;
            }
            if left_hash == right_hash {
                if !set.contains(&left_hash) {
                    set.insert(left_hash);
                    ans += 1;
                }
            }
        }
        ans
    }
    pub fn distinct_echo_substrings(text: String) -> i32 {
        let chars: Vec<char> = text.chars().collect();
        let mut ans = 0;
        for len in 1..=chars.len() / 2 {
            ans += Solution::hash(&chars, len);
        }
        ans
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值