LeetCode/solutions/459. Repeated Substring Pattern.md

2.9 KiB
Raw Blame History

459. Repeated Substring Pattern

思路

判断一个字符串是否由某个子字符串重复若干次构成。
注意substr的用法
substr(pos, len): 从位置pos开始跨越len个字符或直到字符串的结尾以先到者为准对象的部分

思路一、直接判断

子字符串的长度从1开始递增直到找到满足题意则返回true找不到就返回false。
时间复杂度O(n^2), 空间复杂度O(1)

思路二、循环移位

类似思路一只是判断是否满足题意时用了比较trick的方法,时间亲测稍快于思路一,但是牺牲了空间。
若当前子串长度为i则若满足题意则将s循环移位i位后的字符串应该与s相等。
时间复杂度O(n^2), 空间复杂度O(n)

思路三、next数组

求s的next数组(从0开始的版本)记next数组的最后一个元素为p若p > 0 并且 size % (size - p) == 0返回True.
时间复杂度O(n)空间复杂度O(n)

C++

思路一

class Solution {
private:
    // bool isOK(string s, const int &sub_len){
    //     for(int i = 0; i < sub_len; i++){
    //         for(int j = 1; j < s.size() / sub_len; j++)
    //             if(s[j * sub_len + i] != s[(j-1) * sub_len + i]) return false;
    //     }
    //     return true;
    // }
    bool isOK(string s, const int &sub_len){ // 这种写法比上面的更简洁貌似也更快
        for(int i = 1; i < s.size() / sub_len; i++)
            if(s.substr(i * sub_len, sub_len) != s.substr(0, sub_len)) return false;
        return true;
    }
public:
    bool repeatedSubstringPattern(string s) {
        for(int i = 1; i <= s.size() / 2; i++){
            if(s.size() % i != 0) continue;
            if(isOK(s, i)) return true;
        }
        return false;
    }
};

思路二

class Solution {
private:     
    string leftShift(string &str, int l){
        string ret = str.substr(l); // substr(pos, len): 从位置pos开始跨越len个字符或直到字符串的结尾以先到者为准对象的部分
        ret += str.substr(0, l);
        return ret;
    }
public:
    bool repeatedSubstringPattern(string str) {
        string nextStr = str;
        int len = str.length();
        if(len < 1) return false;
        for(int i = 1; i <= len / 2; i++){
            if(len % i == 0){
                nextStr = leftShift(str, i);
                if(nextStr == str) return true;
            }
        }
        return false;
    }
};

思路三

class Solution {
public:
    bool repeatedSubstringPattern(string str) {
        int i = 1, j = 0, n = str.size();
        vector<int> next(n+1,0);
        while( i < str.size() ){
            if( str[i] == str[j] ) next[++i]=++j;
            else if( j == 0 ) i++;
            else j = next[j];
        }
        return next[n]&&next[n]%(n-next[n])==0;
    }
};