求一个字符串中连续出现次数最多的子串

题目:求一个字符串中连续出现次数最多的子串 ,给出分析和代码。

分析: 一个字符串连续出现次数最多的字符串:

   将该连续出现多次的字符串称为循环节,有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);

}




  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值