题目
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
思路
一、求解next数组
首先这个数组索引代表当前最长的前后缀长度,例如:
字符串: a b a b a b a b
next数组:0 0 1 2 3 4 5 6
求解过程:
- 取两个索引,i代表后缀末尾,j代表前缀末尾,如果s[i] == s[j],说明匹配上了,就让j++, 然后next[i] = j
- 如果没匹配上,需要让前缀回退,直到回退到j=0,或者找到一样的,所以代码如下:
void getNext(vector<int> &next, string& s){
int i = 1;
int j = 0;
next[j] = 0;
for(int i = 1; i <next.size(); i++){
while(j > 0 && s[j] != s[i]){
j = next[j - 1];
}
if(s[i]== s[j]){
j++;
next[i] = j ;
}
}
}
二、 找出next数组的规律
如果s不能由其多个最小子串重复组成,比如"aabaaba"
字符串: a a b a a b a
next数组:0 1 0 1 2 3 4
再来一个可以由多个最小子串重复组成的字符串,比如"abcabcabcabc"
字符串: a b c a b c a b c a b c
next数组:0 0 0 1 2 3 4 5 6 7 8 9
可以看到,如果是可以由最小子串重复组成的话,0的数目就是最小重复子串的数目,而且一定可以被字符串整除。
因此,代码如下:
bool repeatedSubstringPattern(string s) {
vector<int> next(s.length(), 0);
getNext(next, s);
if(s.length() - next[s.length() - 1] )
if(next[s.length() - 1] != 0 && s.length() % (s.length() - next[s.length() - 1]) == 0)
return true;
return false;
}