459. 重复的子字符串

459. 重复的子字符串

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

示例 1:

输入: "abab"

输出: True

解释: 可由子字符串 "ab" 重复两次构成。
示例 2:

输入: "aba"

输出: False
示例 3:

输入: "abcabcabcabc"

输出: True

解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/repeated-substring-pattern
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 1.枚举

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        n = len(s)
        for i in range(1, n // 2 + 1):
            if n % i == 0:
                if all(s[j] == s[j - i] for j in range(i, n)):
                    return True
        return False

Python all() 函数

2、字符串匹配

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        return (s + s).find(s, 1) != len(s)

  

3、KMP字符串快速匹配算法,算法复杂度O(m+n);

先计算next数组然后利用next数组

class Solution {
public:
    bool kmp(const string& query, const string& pattern) {
        int n = query.size();
        int m = pattern.size();
        vector<int> fail(m, -1);
        //计算next数组
        for (int i = 1; i < m; ++i) {
            int j = fail[i - 1];
            while (j != -1 && pattern[j + 1] != pattern[i]) {
                j = fail[j];
            }
            if (pattern[j + 1] == pattern[i]) {
                fail[i] = j + 1;
            }
        }
        //根据next数组实现跳转
        int match = -1;
        for (int i = 1; i < n - 1; ++i) {//因为是这个题目,所以需要从1开始,普通的匹配从0开始
            while (match != -1 && pattern[match + 1] != query[i]) {
                match = fail[match];
            }
            if (pattern[match + 1] == query[i]) {
                ++match;
                if (match == m - 1) {
                    return true;
                }
            }
        }
        return false;
    }

    bool repeatedSubstringPattern(string s) {
        return kmp(s + s, s);
    }
};

 

4、优化的KMP

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        def kmp(pattern: str) -> bool:
            n = len(pattern)
            fail = [-1] * n
            for i in range(1, n):
                j = fail[i - 1]
                while j != -1 and pattern[j + 1] != pattern[i]:
                    j = fail[j]
                if pattern[j + 1] == pattern[i]:
                    fail[i] = j + 1
            return fail[n - 1] != -1 and n % (n - fail[n - 1] - 1) == 0
        
        return kmp(s)

5、Hash表做法

统计出每种字母的个数,根据字母的个数判断每种字母可被均分的段数,也就是求除1外的因数
将这些因数求交集,也就是整个字符串可能重复的次数。
对每一种次数进行检验,如果都不满足,返回False

class Solution(object):
    def repeatedSubstringPattern(self, s):
        """
        :type s: str
        :rtype: bool
        """
        hash_map = {}
        for c in s:
            if c not in hash_map:
                hash_map[c] = 1
            else:
                hash_map[c] += 1
        record = []
        for v in hash_map.values():
            record.append(set(self.getFactor(v)))
        temp = record[0]
        for i in range(1, len(record)):
            temp &= record[i]
        yes = [0] * len(temp)
        temp = list(temp)
        for j in range(len(temp)):
            length = len(s) / temp[j]
            start_list = [i * length for i in range(temp[j])]
            for i in range(len(start_list) - 1):
                if s[start_list[i]:start_list[i] + length] != s[start_list[i + 1]:start_list[i + 1] + length]:
                    yes[j] = 1
                    break
        return 0 in yes
    def getFactor(self, n):
        result = []
        for i in range(2, n + 1):
            if n % i == 0:
                result.append(i)
        return result

  

原文地址:https://www.cnblogs.com/noticeable/p/14093646.html