题目:求一个字符串中连续出现次数最多的子串 ,给出分析和代码。
分析: 一个字符串连续出现次数最多的字符串:
将该连续出现多次的字符串称为循环节,有3个属性:
(1) 循环节的首地址,即首字符的指针。 substr
(2) 循环节的长度。
(3 )循环节出现的次数。
求str[i]为首字符的所有循环节中出现次数最多的循环节,(i= 0,1, 2,.... len -1);
在所有的以s[i]为首字符的出现次数最多的循环节中选择出现次数最多的循环节。
由于循环节是连续的,如果存在第二个循环节,就有可能存在更多的循环节。
c语言程序实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100000
void getMaxCyclicSubString(const char *str, const char **substr, int *substr_len, int *max_count);
char str[MAX_LEN];
int main(int argc, char *argv[]) {
char *substr;
int substr_len;
int max_count;
int i;
int j;
int line = 0;
scanf("%s", str);
while(str[0] != '#') {
getMaxCyclicSubString(str, &substr, &substr_len, &max_count);
printf("%s %d: ", "Case", ++line);
for(i = 0; i < max_count; ++i) {
for(j=0; j < substr_len; ++j){
printf("%c", substr[j]);
}
}
printf("\n");
scanf("%s", str);
}
return 0;
}
void getMaxCyclicSubString(const char *str, const char **substr, int *substr_len, int *max_count) {
int i;
int j;
int k;
int count = 1;
int sub_len = 1;
*substr = str;
*substr_len = 1;
*max_count = 1;
int len = strlen(str);
for(i = 0; i < len; ++i) {
for(j = i + 1; j < len; ++j) {
sub_len = j - i; //循环节的长度
count = 1; //长度为sub_len的循环节的初始计数
if(j + sub_len -1 < len && !strncmp(str + i, str + j, sub_len)) {
++count; //循环节出现第二次
for(k = j + sub_len; k < len; k += sub_len) { //测试循环节是否接着出现
if(k + sub_len - 1 < len && !strncmp(str + i, str + k, sub_len)) {
++count;
}else {
break;
}
}
//更新出现次数最多的循环节
if(*max_count < count) {
*substr = str + i;
*max_count = count;
*substr_len = sub_len;
}
//循环节出现次数相同时,保留字典序较小的循环节
if(*max_count == count){
if(sub_len < *substr_len) {
if(strncmp(str + i, *substr, sub_len) <= 0) {
*substr = str + i;
*substr_len = sub_len;
}
}else {
if(strncmp(str + i, *substr, *substr_len) < 0) {
*substr = str + i;
*substr_len = sub_len;
}
}
}
}
}
//循环节都只出现一次
if(1 == *max_count){
if(str[i] < **substr) {
*substr = str + i;
}
}
}
}
C++实现:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
pair<int, string> getMaxCyclicSubString(const string & str);
int main(int argc, char *argv[]) {
string str;
int count = 0;
pair<int, string> result;
cin >> str;
while(str[0] != '#') {
result = getMaxCyclicSubString(str);
cout << "Case " << ++count << ":";
for(int i = 0; i < result.first; ++i) {
cout << result.second ;
}
cout << endl;
cin >> str;
}
return 0;
}
pair<int, string> getMaxCyclicSubString(const string &str) {
vector<string> substrs;
string substr = str.substr(0, 1);
int max_count = 1;
int count = 1;
int len = str.length();
for(int i = 0; i < len; ++i) {
substrs.push_back(str.substr(i, len-i)); //取子串
//cout << str.substr(i, len-i) << endl;
}
for(int i = 0; i < len; ++i) {
for(int j = i + 1; j < len; ++j) {
int sub_len = j - i; //确定循环节的长度
count = 1;
if(substrs[i].substr(0, sub_len) == substrs[j].substr(0, sub_len) ) { //存在循环节
++count;
for(int k = j + sub_len; k < len; k += sub_len) { //更多的循环节
if(substrs[i].substr(0, sub_len) == substrs[k].substr(0, sub_len)) {
++count;
}else {
break;
}
}
//cout << "count = " << count << endl;
if(count >= max_count) {
string cur_substr = substrs[i].substr(0, sub_len);
if(count == max_count) {
if(cur_substr < substr){
substr = cur_substr;
}
}else {
max_count = count;
substr = cur_substr;
}
}
}
}
if(1 == max_count) {
string cur_substr = substrs[i].substr(0, 1);
if(cur_substr < substr ) {
substr = cur_substr;
}
}
}
return make_pair(max_count, substr);
}