Repeated Substring Pattern

Given a non-empty string check if it can be constructed by taking a
substring of it and appending multiple copies of the substring
together. You may assume the given string consists of lowercase
English letters only and its length will not exceed 10000.

Example:
Input: "abab" Output: True
Explanation: It's the substring "ab" twice.

给定一个字符串,判断该字符串能否由其自身的某一个子串通过不断重复而得到。

暴力法

复杂度

时间 O(N^2) 空间O(1)

思路

如果一个字符串s能够通过其某一子串不断重复而得到,那么这个子串的开头肯定是这个字符串s的开头。如果要符合题目条件,子串至少要重复2次(比如abcabc),而至多可以重复字符串s的长度那么多次(比如aaaaa)。我们穷举所有可能的倍数,一一测试,就能得到是否存在这么一个子串,通过不断重复而得到母串s。

class Solution:
    def repeatedSubstringPattern(self, s):
        """
        :type s: str
        :rtype: bool
        """
        if len(s) <= 1:
            return False
        length = len(s)
        for times in range(2, len(s) + 1): # 最少重复2次,最多重复length次
            if length % times == 0 and times * s[0:length//times] == s: # 复制times次数,看是否和母串相同
                return True
        return False

双倍法

复杂度

时间 O(N) 空间O(1)

思路

这种解法其实类似于数学题,假设字符串S由k个字符串a组成,那么如果将两个字符串S相连成为2S时,其中必定出现了2k次字符串a。由于k必定大于等于2(如果k=1,那a就是S了,不成立),那么在2k个字符串a的中间部分肯定能找到k个字符串a,而k个字符串a就是字符串s(比如k=2时,2S = aaaa = aSa),为了避免拿到前面和后面的k个字符串a(k=2时,避免类似于SaaaaS的情况),我们将2S的首尾字母都去掉,再在其中寻找S。由此证明,如果字符串S能由k个a组成的话,必定能在2S中间部分找到一个S。(这里只证明了充分性,未证明必要性)

class Solution:
    def repeatedSubstringPattern(self, s):
        """
        :type s: str
        :rtype: bool
        """
        return s in (s * 2)[1:-1] if len(s) > 1 else False

ethannnli
858 声望360 粉丝