最长重复子串问题

18 篇文章 0 订阅
17 篇文章 1 订阅

最长重复子串是指在一个字符串中找出最长的出现两次或两次以上的子串,例如abcdeabbcde,则bcde则是最长的重复子串。

最直观的解法是穷举所有的子串,和原串进行对比,从而选出最长的重复子串。

#include <stdio.h>
#include <string.h>


int commonLen(const char *str1, const char *str2){
        int len = 0;
        if(str1 == NULL || str2 == NULL){
                return 0;
        }
        while(*str1 && * str2 && *str1 == *str2){
                str1++;
                str2++;
                len++;
        }
        return len;
}

int LRS(const char *str){
        if(str == NULL){
                return 0;
        }
        int i, j;
        int maxlen = 0, curlen = 0, maxindex = 0;
        int len = strlen(str);
        for(i = 0; i < len; i++){
                for(j = i + 1; j < len; j++){
                        curlen = commonLen(str + i, str + j);
                        if(curlen > maxlen){
                                maxlen = curlen;
                                maxindex = i;
                        }
                }
        }
        for(i = 0; i < maxlen; i++){
                printf("%c", *(str + maxindex + i));
        }
        return maxlen;
}

int main(){
        char *str = "abcdeabbcde";
        int len = LRS(str);
        printf("Max LRS = %d\n", len);
}
这种算法的效率是O(N^3),效率不高,使用过KMP算法的同学会联想到这其实就是在求next数组的最大值问题,例如“abcdabcde”,它的next数组为:

-1      0       0       0       0       1       2       3       4       0

各个子串的next数组的最大值就是最长重复子串的长度。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int maxNext(const char *s, int _next[]){
        _next[0] = -1;
        int i = 0;
        int j = -1;
        int max = 0;
        int len = strlen(s);
        while(i < len){
                if(j == -1 || s[i] == s[j]){
                        i++;
                        j++;
                        _next[i] = j;
                        if(j > max){
                                max = j;
                        }
                }else{
                        j = _next[j];
                }
        }
        return max;
}

int LRS_KMP(const char *str){
        int len = strlen(str);
        int index = 0;
        int max = 0;
        int maxindex = 0;
        int *_next = (int *)malloc(len * sizeof(int));
        int i;
        for(i = 0; i < len - 1; i++){
                int curmax = maxNext(str + i, _next);
                if(curmax > max){
                        max = curmax;
                        maxindex = i;
                }
        }
        for(i = 0; i < max; i++){
                printf("%c", *(str + maxindex + i));
        }
        return max;
}

int main(){
        char *str = "abaabaaabaaaab";
        int len = LRS_KMP(str);
        printf("Max LRS = %d\n", len);
}





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值