题目链接:https://leetcode-cn.com/problems/repeated-substring-pattern
题目描述:
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
示例 1:
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
示例 2:
输入: "aba"
输出: False
示例 3:
输入: "abcabcabcabc"
输出: True
解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)
解题:
kmp算法中,求next数组尤其重要,在这一题中,实际就是求最长公共前后缀。在这里没有讲next数组右移一位,直接用前后缀表,所以如果 next[len - 1] != 0,则说明字符串有最长相同的前后缀(就是字符串里的前缀子串和后缀子串相同的最长长度)。
最长相等前后缀的长度为:next[len - 1]。
数组长度为:len。
如果len % (len - (next[len - 1])) == 0 ,则说明 (数组长度-最长相等前后缀的长度) 正好可以被 数组的长度整除,说明有该字符串有重复的子字符串。
class Solution {
public:
vector<int> prefix_table(string pattern)
{
int n = pattern.size();
vector<int> prefix(n, 0); //prefix[k]表示以k结尾的最长公共前后缀的长度值
int i = 0; //前缀指针
int j = 1; //后缀指针
for(;j < n; j++ )
{
while(i > 0 && pattern[i] != pattern[j])
{
i = prefix[i - 1];
}
if(pattern[i] == pattern[j]){
i++;
prefix[j] = i;
}
}
return prefix;
}
bool repeatedSubstringPattern(string s) {
int len = s.size();
vector<int> next;
next = prefix_table(s);
if(next[len - 1] != 0 && (len % (len - next[len - 1])) == 0)
return true;
else
return false;
}
};