目录
给出一字符串,判断其是否由重复子字符串组成。
即:
输入:asdasdasd输出:true
输入asdfg
输出:false
与kmp的联系
看了之前介绍的KMP算法http://t.csdnimg.cn/698L3http://t.csdnimg.cn/698L3,我们很快就能想到其中的next数组,next数组存的是最长相等前后缀。
思考:
试想在一个由重复子字符串组成的字符串里,如asdasdasd,此时他末尾的next数组元素为6(即asdasd(前缀)==asdasd(后缀)),若这个字符串确实是由重复子字符串asd组成,那么这个6即为不包含第一个asd的其他字符的数量总和(在双指针法中,开头3个字符没有相等前后缀,所以快指针比慢指针多走了3个字符,而到最后快指针走到末尾时,慢指针始终比他慢3个字符)。
所以整个字符串长度减去末尾next数组元素会得到asd的长度,即一个循环体的长度,此时我们让整个字符串长度%一个循环体的长度,若==0,则整个字符串是以这个子字符串为循环的。
整体代码:
class str
{
public:
void getNEXT(vector<int> next, const string& s)
{
int j = 0;
next[0] = 0;
for (int i = 1; i < s.size(); i++)
{
while (s[i] != s[j] && j > 0)
{
j = next[j - 1];
}
if (s[i] == s[j])
{
j++;
next[i] = j;
}
}
}
bool Str(const string& s)
{
vector<int> next;
getNEXT(next, s);
if (next[s.size() - 1] != 0 && s.size() % (s.size() - next[s.size() - 1]) == 0)
return true;
return false;
}
};
此外
可能有人会注意到,如果整个字符串全是乱的,如asdfghj,那这样末尾的next数组元素即为0,s.size()%(s.size()-0)==0,即这种情况也会被整除,所以为了避免这种情况,我们在代码中添加了next[s.size()-1]!=0&& s.size() % (s.size() - next[s.size() - 1]) == 0
谢谢。