【字符串】最长不重复子串

参考资料:

          http://www.ahathinking.com/archives/123.html 

题目:

       从一个字符串中找到一个连续子串,该子串中任何两个字符不能相同,求子串的最大长度并输出一条最长不重复子串

思路:

       使用一个数组dp[i]记录到当前下标i的元素为止,最长的不重复子串长度。使用lastIndex记录上一个最长不重复子串的开始位置,

使用before表示当前元素重复出现的上一个位置,那么有如下的状态方程:

image

void lnrs_1(const char *s ,int size)
{
    int visit[256]={0};        //记录上一次元素出现下标
    memset(visit,-1,256*4);
    int *dp=new int[size];    //至下标为i的元素的最长不重复子串长度
    memset(dp,0,size*4);
visit[s[0]]=0;
dp[0]=1;
int endIndex=0; //最长不重复子串结束下标 int maxlen=0; //最长不重复子串长度 int lastIndex=0; //上一个不重复子串的开始位置 for(int i=1;i<size;i++) { if(visit[s[i]]==-1) //当前元素未重复出现 { dp[i]=dp[i-1]+1; visit[s[i]]=i; } else { if(lastIndex > visit[s[i]]) { dp[i]=dp[i-1]+1; } else { dp[i]=i-visit[s[i]]; lastIndex=visit[s[i]]+1; } visit[s[i]]=i; } if(dp[i] > maxlen) { maxlen=dp[i]; endIndex=i; } } cout<<"index:"<<endIndex-maxlen+1<<","<<endIndex<<endl; delete[] dp; }

改进版本:

      考虑上上述实现,dp[i]表示下标为i的元素为止的最长重复子串,dp[i]的作用是更新maxlen(最长不重复子序列长度),可以使用curlen

表示至当前元素的最长不重复子串的长度,用于更新maxlen。

算法时间复杂度:O(n),空间复杂度O(1)

void  lnrs(const char *s,int size)
{
    int visit[256];    //记录当前元素上一次重复出现的位置
    memset(visit,-1,256*4);
    visit[s[0]]=0;
    int endIndex=0;      //最长不重复子串结尾位置
    int maxLen=0;        //最长不重复子串长度
    int lastIndex=0;  //上一个不重复子串的开始位置
    int curlen=1;     //至当前元素不重复子串的长度

    for(int i=1;i<size;i++)
    {
        if(visit[s[i]]==-1)
        {
            curlen++;
            visit[s[i]]=i;
        }
        else
        {
            if(lastIndex > visit[s[i]])
            {
                curlen++;
            }
            else
            {
                curlen=i-visit[s[i]];
                lastIndex=visit[s[i]]+1;
            }
            visit[s[i]]=i;
        }

        if(curlen > maxLen)
        {
            maxLen=curlen;
            endIndex=i;
        }
    }
    cout<<"maxIndex:["<<endIndex-maxLen+1<<","<<endIndex<<"]"<<endl;
}
原文地址:https://www.cnblogs.com/luosongchao/p/3684171.html