数据结构之最大重复子串

说明:

最大重复子串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\n",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\n",p1);
//    printf("(char const*)p1=0x%p\n",(char const*)p1);
//    printf("*(char const**)p1=0x%p\n",*(char const**)p1);
//    printf("**(char const**)p1=0x%c\n",**(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\n",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\n",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\n",pos);
    }
    else printf("Substrin not found!\n");
}

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;
}

 

posted @ 2013-11-20 14:03  IT_cnblogs  阅读(682)  评论(0编辑  收藏  举报