最长不重复子串

算法参考:http://sxnuwhui.blog.163.com/blog/static/1370683732012513103935198/


找到一个字符串中的一个连续子串,这个子串内不能有任何两个字符是相同的,并且这个子串是符合要求的最长的。例如输入"abcbef",输出"cbef"。

O(N)的算法,具体思路如下:
以abcbef这个串为例,用一个数组pos记录每个元素曾出现的下标,初始化为-1。从s[0]开始,依次考察每个字符,例如pos['a'] == -1,说明a还未出现过,令pos['a'] = 0,视为将‘a’加入当前串,同时长度+1,同理pos['b'] = 1,pos['c'] = 2,考察s[3],pos['b'] != -1,说明'b'在前面已经出现过了,此时可得到一个不重复串"abc",刷新当前的最大长度,然后更新pos['b']及起始串位置。

过程如下:
1、建一个256个单元的数组,每一个单元代表一个字符,数组中保存上次该字符出现的位置;
2、依次读入字符串,同时维护数组的值;
3、如果遇到冲突了,考察当前起始串位置到冲突字符的长度,如果大于当前最大长度,则更新当前最大长度并维护冲突字符的位置,更新起始串位置,继续第二步。


#include <iostream>
#include <string>
using namespace std;

char* GetMaxSubStr( char*str )
{
    int hash[256]; //hash记录每个字符的出现位置
    for (int i = 0; i < 256; i++)//初始化
    {
        hash[i] = -1;
    }
    int CurrentStart = 0, CurrentLength = 0, MaxStart = 0, MaxEnd = 0;
    int strLen = strlen(str);
    for(int i = 0; i < strLen; i++)
    {
        if(CurrentStart > hash[str[i]]) //如果没有重复
        {
            hash[str[i]] = i;
        }
        else
        {
            CurrentLength = i - CurrentStart; //当前长度
            if(CurrentLength > MaxEnd-MaxStart)//如果当前长度最长
            {
                MaxEnd = i;
                MaxStart = CurrentStart;
            }
            CurrentStart = hash[str[i]] + 1; //更新当前最长的起点
            hash[str[i]] = i; //更新字符出现的位置
        }
    }
    if (MaxEnd == 0)//没有重复字符,返回源串
    {
        char* reStr = new char[strLen + 1];
        strcpy(reStr, str);
        return reStr;
    }
    CurrentLength = strLen - CurrentStart; //当前长度
    if(CurrentLength > MaxEnd - MaxStart)//如果当前长度最长
    {
        MaxEnd = strLen;
        MaxStart = CurrentStart;
    }
    int MaxLength = MaxEnd - MaxStart;
    char* reStr = new char[MaxLength + 1];
    memset(reStr, 0, MaxLength + 1);
    strncpy(reStr, str + MaxStart, MaxLength);
    return reStr;
}

int main()
{
    string str = GetMaxSubStr("abcbef");
    cout << str << endl;

    return 0;
}


实战题目:Leet Code Longest Substring Without Repeating Characters



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值