算法参考: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