• 数据结构之最大重复子串


    说明:

    最大重复子串Longest repeat string,简称LRS,即在一个字符串中寻找最长的重复子串

    例如"banana",则最大重复子串为"ana"

    三种方法

    方法1:暴力搜索法,复杂度O(N^2)

    方法2:使用后缀数组的方法

    方法3:利用KMP方法中的next数组

    同时补充了个KMP的代码,与本题无关

    // project1.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include<string.h>
    #include<algorithm>
    #define LENGTH 1000
    
    //复杂度O(n^2)
    void max_substr(char str[]){
        //寻找最大重复子串
        int max=0,first_beg,second_beg;
        for(int i=0;i<strlen(str);i++){//第一个子串开始字符
            for(int j=i+1;j<strlen(str);j++){//第二个子串开始字符
                int cur_max=0;
                for(int k=i,l=j;k<strlen(str)&&l<strlen(str);k++,l++){
                    if(str[k]==str[l])
                        cur_max++;
                    else break;
                }
                if(cur_max>max){
                    first_beg=i;
                    second_beg=j;
                    max=cur_max;
                }
            }
        }
        printf("Max Repeat Substring length=%d
    ",max);
    }
    
    int compare(const void *p1,const void *p2){
        //C++标准规定,const关键字放在类型或变量名之前等价的
        //char * const cp; ( * 读成 pointer to ) cp is a const pointer to char 
        //const char * p; p is a pointer to const char; 
        //char const * p; 同上因为C++里面没有const*的运算符,所以const只能属于前面的类型
        
        //排序没成功,因为p1和p2是指向字符的指针的指针
    //    return strcmp((char const*)p1,(const char*)p2);
    
    //    printf("p1=0x%p
    ",p1);
    //    printf("(char const*)p1=0x%p
    ",(char const*)p1);
    //    printf("*(char const**)p1=0x%p
    ",*(char const**)p1);
    //    printf("**(char const**)p1=0x%c
    ",**(char const**)p1);
        return strcmp(*(char** const)p1,*(const char**)p2);
    }
    
    //方法2:使用后缀数组
    void LRS_suffix(char str[]){
        int len=strlen(str);
        //指针数组,数组每个元素存的是char*的指针
        char **suffix=new char*[LENGTH];
        for(int i=0;i<len;i++)
            suffix[i]=str+i;
    
        //后缀数组按指向的内容排序
        qsort(suffix,len,sizeof(char*),compare);
    
        int max=0;
        for(int i=0;i<len - 1;i++){
            int cur_max=0;
            char *p1=suffix[i],*p2=suffix[i+1];
            while(*p2 && *p1++==*p2++)
                cur_max++;
            if(cur_max>max)
                max=cur_max;
        }
        delete [] suffix;
        printf("Max Repeat Substring length=%d
    ",max);
    }
    
    void KMP_getnext(char str[],int next[]){
        next[0]=-1;
        int j=0,k=-1;
        while(j<=strlen(str)){
            if(k==-1 || str[j]==str[k])
                next[++j]=++k;
            else k=next[k];
        }
    }
    
    //方法3:KMP法求最大重复子串.
    //最大重复子串相当于next数组的最大值max{next[i]}
    void KMP_substr(char str[]){
        //求max{next[i]}
        int max=0;
        for(int i=0;i<strlen(str);i++){
            int next[LENGTH]={0};
            char *substr=(str+i);
            KMP_getnext(substr,next);
            for(int j=0;j<=strlen(substr);j++)
                if(next[j]>max)
                    max=next[j];
        }
        printf("Max Repeat Substring length=%d
    ",max);
    }
    //KMP匹配,与本题无关
    void KMP(char str[],char substr[]){
        int next[LENGTH];
        KMP_getnext(substr,next);
        int i=0;//主串位置
        int j=0;//模式串位置
        int pos=-1;//匹配的位置
        int len1=strlen(str),len2=strlen(substr);
        while(i<len1 && j<len2){
            if(j==-1 || str[i]==substr[j]){
                i++;j++;
            }
            else j=next[j];
        }
        if(j==strlen(substr)){//找到子串
            pos=i-j;
            printf("Substring found! It begins at %d
    ",pos);
        }
        else printf("Substrin not found!
    ");
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        char str1[LENGTH]="banana";
        char str2[LENGTH]="abcdefabcdeabcdabcaba";
        char str3[LENGTH]="12345612343245656123";
        char str4[LENGTH]="cdab";
        char str5[LENGTH]="banaa";
        char str6[LENGTH]="2456561";
        max_substr(str1);max_substr(str2);max_substr(str3);
        LRS_suffix(str1);LRS_suffix(str2);LRS_suffix(str3);
        KMP_substr(str1);KMP_substr(str2);KMP_substr(str3);
        KMP(str2,str4);KMP(str1,str5);KMP(str3,str6);
        return 0;
    }
  • 相关阅读:
    nm命令与符号说明
    (OK) 编译xerces-c-3.1.2(动态库)—CentOS 7— android-ndk
    【19.00%】【vijos p1906】联合权值
    【30.00%】【vijos 1909】寻找道路
    【23.33%】【hdu 5945】Fxx and game
    【32.26%】【codeforces 620C】Pearls in a Row
    【第400篇题解纪念2016年10月28日】【28.10%】【codeforces 617E】XOR and Favorite Number
    【20.00%】【codeforces 44G】Shooting Gallery
    【19.27%】【codeforces 618D】Hamiltonian Spanning Tree
    【17.00%】【codeforces 621D】Rat Kwesh and Cheese
  • 原文地址:https://www.cnblogs.com/abc123456789/p/3433437.html
Copyright © 2020-2023  润新知