输入一个字符串,如何求最大重复出现的字符串呢?比如输入ttabcftrgabcd,输出结果为abc, canffcancd,输出结果为can。
给定一个字符串,求出其最长的重复子串。
分析:使用后缀数组,对一个字符串生成相应的后缀数组后,然后再排序,排完序依次检测相邻的两个字符串的开头公共部分。
这样的时间复杂度为:
- 生成后缀数组 O(N)
- 排序 O(NlogN*N) 最后面的 N 是因为字符串比较也是 O(N)
- 依次检测相邻的两个字符串 O(N * N)
故最终总的时间复杂度是 O(N^2*logN)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10000
char str[SIZE], *pstr[SIZE];
int pstrcmp(char* p, char* q) {
return strcmp(*(char* const *) p, *(char* const *) q);
}
int getCommonLen(char* p, char* q) {
int len = 0;
while (*p && *(p++) == *(q++)) {
len++;
}
return len;
}
void initRearArr(char* src) {
int len = strlen(src);
int i = 0;
for (i = 0; i < len; ++i) {
pstr[i] = &str[i];
str[i] = src[i];
}
str[i] = '\0';
}
char* getMaxRepeatSubStr() {
int i = 0;
int len = strlen(str);
int maxLen = 0, maxId = 0;
int temp = 0;
for (i = 0; i < len - 1; i++) {
if ((temp = getCommonLen(pstr[i], pstr[i + 1])) > maxLen) {
maxLen = temp;
maxId = i;
}
}
char* p = pstr[maxId];
char* result = calloc(sizeof(char), maxLen + 1);
for (i = 0; i < maxLen; i++) {
result[i] = *(p + i);
}
result[i] = '\0';
return result;
}
int main(void) {
char* src = "canffcancd";
initRearArr(src);
qsort(pstr, strlen(src), sizeof(char*), pstrcmp);
puts("最大重复子串:");
puts(getMaxRepeatSubStr());
return EXIT_SUCCESS;
}