leetcode
leetcode 401 ~ 450
重复的子字符串

重复的子字符串

难度:

标签:

题目描述

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

 

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

 

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

代码结果

运行时间: 25 ms, 内存: 16.1 MB


/*
 * 题目思路:
 * 同样的思路,我们使用 Java Stream API 实现此功能。
 * 我们将 s 和自身拼接,然后移除第一个和最后一个字符,
 * 再检查原字符串 s 是否出现在新字符串中。
 */
 
import java.util.stream.IntStream;
 
public class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String new_s = s + s;
        // 使用 IntStream 查找是否存在 s
        return IntStream.range(1, new_s.length() - 1)
                        .anyMatch(i -> new_s.substring(i, i + s.length()).equals(s));
    }
}

解释

方法:

这个题解的思路是,如果字符串 s 可以由一个子串重复多次构成,那么将 s 和自身拼接成一个新字符串 doubled_str,并去掉 doubled_str 的首尾字符得到 sliced_str,那么原字符串 s 一定会作为子串出现在 sliced_str 中。反之,如果 s 不能由一个子串重复多次构成,那么 s 就不会出现在 sliced_str 中。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中提到,通过拼接字符串并去掉首尾字符来检测重复子串。这种方法为什么能准确判断出字符串是否可以由其子串重复构成?
这种方法的原理基于字符串的周期性。如果字符串s可以由其子串t重复多次构成,那么将s和自身拼接后,形成的新字符串doubled_str中至少包含两个完整的s,即形如s + s = t...t + t...t。去掉首尾字符后,s的每个重复周期在新字符串sliced_str中仍然存在,只是首尾各少了一部分。因此,如果s在sliced_str中可以找到,则说明s具有周期性,即可以由更短的子串重复组成。反之,如果s不具有这样的重复结构,那么s不会在sliced_str中完整出现。
🦆
题解中生成了一个新的字符串 doubled_str 并从中去掉首尾字符得到 sliced_str,这种操作是否可能导致原始字符串 s 的某些重复模式在 sliced_str 中丢失?
去掉首尾字符主要是为了消除边界影响。例如,如果字符串s是由子串t重复构成的,去掉首尾字符后,虽然首尾可能会丢失部分重复的子串t,但由于doubled_str中包含至少两个s,这种丢失不会影响中间部分的s的完整出现。因此,这种操作不会导致s的重复模式在sliced_str中丢失,只要s是由子串重复构成的,它仍然会在sliced_str中出现。
🦆
针对非常短的字符串,比如长度为1或2的字符串,这种方法是否仍然有效?如果 s = 'a' 或 s = 'aa',结果会是怎样?
对于非常短的字符串,这种方法同样有效。例如,如果s = 'a',则doubled_str = 'aa',去掉首尾字符后变为空字符串,s显然不会出现在空字符串中,因此返回false。而对于s = 'aa',则doubled_str = 'aaaa',去掉首尾字符后得到'aa',s在sliced_str中完整地出现了,因此返回true。这说明无论字符串s的长度如何,该方法都能正确判断s是否由其子串重复构成。
🦆
在判断 s 是否出现在 sliced_str 中时,是否考虑了所有可能的出现位置,还是只检查了某一特定的位置?
在判断s是否出现在sliced_str中时,考虑了所有可能的出现位置。使用Python的'in'操作符来检查s是否为sliced_str的子串,这个操作会检查sliced_str的所有可能位置以确定s是否为其子串。因此,这种方法不局限于检查特定位置,而是全面地检查整个sliced_str。

相关问题

找出字符串中第一个匹配项的下标

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1

 

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

 

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystackneedle 仅由小写英文字符组成

重复叠加字符串匹配

给定两个字符串 ab,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1

注意:字符串 "abc" 重复叠加 0 次是 "",重复叠加 1 次是 "abc",重复叠加 2 次是 "abcabc"

 

示例 1:

输入:a = "abcd", b = "cdabcdab"
输出:3
解释:a 重复叠加三遍后为 "abcdabcdabcd", 此时 b 是其子串。

示例 2:

输入:a = "a", b = "aa"
输出:2

示例 3:

输入:a = "a", b = "a"
输出:1

示例 4:

输入:a = "abc", b = "wxyz"
输出:-1

 

提示:

  • 1 <= a.length <= 104
  • 1 <= b.length <= 104
  • ab 由小写英文字母组成