请使用C++语言的KMP算法解答这道题:给定一个非空的字符串 s 检查是否可以通过由它的一个子串重复多次构成。
思路:
- 如果字符串长度为1,显然不能重复多次构成。
- 如果字符串长度大于1,那么最多可以重复多少次呢?假设字符串可以由子串s'重复k次构成,那么s的长度应该为k * s'的长度。因此,k = s.length() / s'.length()。如果k为0,则s'长度比s长,显然不可能由s'构成;如果k为1,则s'就是s本身,也不需要重复;否则,我们需要检查s是否由k个s'构成,即判断s是否等于k * s'。
- 如何判断s是否等于k * s'呢?我们可以使用KMP算法,先在s中匹配s',然后在s中从s'.length()开始匹配s',直到匹配k次为止,看最后剩下的字符串是否为空。
代码实现:
#include <iostream>
#include <vector>
using namespace std;
// KMP算法
vector<int> get_next(string& pattern) {
int n = pattern.length();
vector<int> next(n, 0);
int i = 1, j = 0;
while (i < n) {
if (pattern[i] == pattern[j]) {
next[i] = j + 1;
i++;
j++;
} else if (j > 0) {
j = next[j - 1];
} else {
i++;
}
}
return next;
}
// 判断s是否可以由一个子串重复多次构成
bool repeatedSubstringPattern(string s) {
int n = s.length();
if (n == 1) {
return false;
}
for (int len = 1; len <= n / 2; len++) {
if (n % len == 0) {
int k = n / len;
string pattern = s.substr(0, len);
vector<int> next = get_next(pattern);
int i = len, j = 0;
while (i < n && j < len && s[i] == pattern[j]) {
i++;
j++;
}
if (j == len) {
j = next[len - 1];
}
for (int t = 2; t <= k; t++) {
while (j < len && s[i] == pattern[j]) {
i++;
j++;
}
if (j != len) {
break;
}
j = next[len - 1];
}
if (i == n && j == 0) {
return true;
}
}
}
return false;
}
// 测试
int main() {
cout << repeatedSubstringPattern("abab") << endl; // true
cout << repeatedSubstringPattern("aba") << endl; // false
cout << repeatedSubstringPattern("abcabcabcabc") << endl; // true
cout << repeatedSubstringPattern("a") << endl; // false
cout << repeatedSubstringPattern("aa") << endl; // true
return 0;
}
原文地址: http://www.cveoy.top/t/topic/bnj1 著作权归作者所有。请勿转载和采集!