[LeetCode] 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 1:

Input: "abab"

Output: True

Explanation: It's the substring "ab" twice.

Example 2:

Input: "aba"

Output: False

Example 3:

Input: "abcabcabcabc"

Output: True

Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)

重复子字符串模板:给定源一个字符串,如果它是由重复的子串组成,则返回true,否则返回false。

1、如果一个字符串由重复的子串组成,那么先枚举所有的子字符串。子字符串的最大长度小于等于源字符串长度的一半。

2、枚举出每一个子字符串后,根据它的长度来判断它是否组成源字符串。

3、判断标准:1)首先子字符串长度要被源字符串整除。2)以子字符串的长度为界,依次取源字符串的子串。判断每个子串是否和枚举的子字符串相等。如果不等,则跳出判断循环,枚举下一个子字符串。

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        for (int i = 1; i <= n / 2; i++) {
            if (n % i == 0) {
                string sub = s.substr(0, i);
                int j;
                for (j = 1; j < n / i; j++) 
                    if (sub != s.substr(i * j, i))
                        break;
                if (j == n / i)
                    return true;
            }
        }
        return false;
    }
};
// 33 ms

 简便方法:

1、令str = s + s

2、然后将str取掉首尾字符

3、在新的str中寻找s,如果找到返回true,否则返回false

public:
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        string str = s + s;
        str = str.substr(1, 2 * n - 2);
        return str.find(s) != -1;
    }
};
// 29 ms

 kmp方法。

假设str长度为len,重复的子串长度为k,则如果真的由连续多个长度为k的子串重复构成str,那么在对str求next时,由于连续对称性(如图,前后两个虚线框内字符串相等),会从next[k+1]开始,1,2,3...地递增,直到next[len]=len-k,且(len-k)%k==0,表示有整数个k

要一直求到next[len]而不是next[len-1],是因为next[len-1]只是表示前len-1个字母的内部对称性,而没有考虑到最后一个字母即str[len-1]

所以求解很简单:先对str求next数组,一直求到next[len],然后看看next[len]是否非零且整除k(k=len-next[len])

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        vector<int> dp(n + 1, 0);
        dp[0] = -1;
        int j = 0, k = -1;
        while (j < n) {
            if (k == -1 || s[j] == s[k])
                dp[++j] = ++k;
            else
                k = dp[k];
        }
        return dp[n] && (dp[n] % (n - dp[n]) == 0);
    }
};
// 42 ms

 参考:http://www.cnblogs.com/liziran/p/6129336.html

原文地址:https://www.cnblogs.com/immjc/p/7553048.html