数据结构之最大不重复串

说明:

最大不重复串Longest not repeat string,简称LNRS,即在一个字符串中寻找连续的,没有重复字符的最长子串

如"banana",LNRS为"ban"

本文实现方法均是在别人的基础上,由本人实现,在此非常感谢大家的无私分享。

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

方法2:由于暴力查找时会有重复查找,所以使用动态规划法提高效率

方法3:针对方法2进行空间优化

方法4:动态规划+hash法

// project1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<string.h>
#define LENGTH 1000
//方法1::暴力查找法,复杂度O(N^2)
void LNRS_hash(char str[]){
    //以*p开始的最大不重复子串
    char *p=str;
    int max=0,pos=0;
    for(int i=0;*(p+i);i++){
        int hash[256]={0};
        int cur_max=0;
        for(int j=i;*(p+j);j++){
            if(hash[(unsigned int)*(p+j)]==0){
                hash[(unsigned int)*(p+j)]++;
                cur_max++;    
            }
            else {
                if(cur_max>max){
                    max=cur_max;
                    pos=i;
                }
                break;
            }
        }
    }
    printf("LNRS length:%d, begins at %d
",max,pos);
}

//动态规划法
void LNRS_dp(char str[]){
    int len=strlen(str);
    /*dp数组存的并不是LNRS,例如'abcdd'
    * dp[4]=0,而不是dp[4]=4
    * 对于dp[n],只有一种情况>dp[n-1]
    * 即str[n]添加到LNRS
    */
    int dp[LENGTH];
    for(int i=0;i<len;i++)//初始LNRS为1
        dp[i]=1;
    int max=0,pos=-1,last_beg=0;
    for(int i=1;i<len;i++){
        int j;
        for(j=i-1;j>=last_beg;j--){
            if(str[j]==str[i]){//出现重复
                dp[i]=i-j;
                last_beg=j+1;
                break;
            }
            else if(j==last_beg) 
                dp[i]=dp[i-1]+1;
            
        }
        if(dp[i]>max){//LNRS加1
            max=dp[i];
            pos=i+1-max;
        }
    }
    printf("LNRS length:%d, begins at %d
",max,pos);
}

//动态规划法--改善空间,针对LNSR_dp的空间优化
void LNRS_dp2(char str[]){
    int len=strlen(str);
    int dp=1;
    int max=0,pos=-1,last_beg=0;
    for(int i=1;i<len;i++){
        int j;
        for(j=i-1;j>=last_beg;j--){
            if(str[j]==str[i]){//出现重复
                dp=i-j;
                last_beg=j+1;
                break;
            }
            else if(j==last_beg) 
                dp++;
            
        }
        if(dp>max){//LNRS加1
            max=dp;
            pos=i+1-max;
        }
    }
    printf("LNRS length:%d, begins at %d
",max,pos);
}

/* LNRS dp + hash 优化 */
void LNRS_dp_hash_impro(char * arr){
    int size=strlen(arr);
    int visit[256];//记录某个字符最近出现的位置
    for(int i=0;i<256;i++)
        visit[i]=-1;
    int maxlen = 0,maxindex = 0;
    visit[arr[0]] = 0;
    int curlen = 1;
    int last_start = 0;
    for(int i = 1; i < size; ++i){
        if(visit[arr[i]] == -1){//未曾出现
            ++curlen;
            visit[arr[i]] = i; /* 记录字符下标 */
        }
        else{//已经出现过
            //如果arr[i]上次出现的位置在last_start之后
            //例如abcdc,i=4时,c出现的位置在last_start(0)之后
            //则肯定无效
            if(last_start <= visit[arr[i]]){
                curlen = i - visit[arr[i]];
                last_start = visit[arr[i]]+1;
                visit[arr[i]] = i; /* 更新最近出现位置 */
            }
            else{
                ++curlen;
                visit[arr[i]] = i; /* 更新最近出现位置 */
            }
        }
        if(curlen > maxlen){
            maxlen = curlen;
            maxindex = i + 1 - maxlen;
        }
    }
    printf("LNRS length:%d, begins at %d
",maxlen,maxindex);
}
int _tmain(int argc, _TCHAR* argv[])
{
    char str1[LENGTH]="banana";
    char str2[LENGTH]="aabbccdjlhiuerkjhefabcdeabcdabcaba";
    char str3[LENGTH]="12341343245656123";
    char str4[LENGTH]="abcdda";
    char str5[LENGTH]="banaa";
    char str6[LENGTH]="2456561";
    
    LNRS_hash(str1);LNRS_hash(str2);LNRS_hash(str3);
    LNRS_dp(str1);LNRS_dp(str2);LNRS_dp(str3);
    LNRS_dp2(str1);LNRS_dp2(str2);LNRS_dp2(str3);
    LNRS_dp_hash_impro(str1);LNRS_dp_hash_impro(str2);LNRS_dp_hash_impro(str3);
    return 0;
}



 

 

 
原文地址:https://www.cnblogs.com/abc123456789/p/3433440.html