给定一个字符串,请找出其中无重复字符的最长子字符串。
样例
例如,在"abcabcbb"
中,其无重复字符的最长子字符串是"abc"
,其长度为 3
。
对于,"bbbbb"
,其无重复字符的最长子字符串为"b"
,长度为1
。
挑战
O(n) 时间
分析:
利用动态规划
首先定义函数f(i)表示以第i个字符为结尾的不包含重复字符的子字符串的最长长度。
当从左至右扫描字符串中的每个字符时,我们利用f(i-1)计算f(i),两者关系如下:
如果第i个字符之前没有出现过(需要定义一个函数,记录每个字符上次出现在字符串中位置的下标),则f(i)=f(i-1)+1.
如果第i个字符出现过,分为两种情况:先计算第i个字符和它上次出现在字符串中的位置的距离,记为d
- d<=f(i-1),则f(i)=d,也证明这个重复字符之间没有其他重复字符了
- d>f(i-1),则f(i)=f(i-1)+1,即上一个重复字符不在f(i-1)对应的最长不重复子字符串之内,不会影响到f(i-1)
代码:
int result(const string&str)
{
int curlength=0;
int maxlength=0;
int*position=new int[26];//假设总共有26种字符
for(int i=0;i<26;i++)
position[i]=-1;//等于-1时证明此字符还未出现过,出现过的字符都被更新了
//其中i用来代表不同的字符,因为abc...的asii码值大于26,所以我们利用str[i]-'a'来代表str[i]字符
for(int i=0;i<str.size();i++)
{
int index=position[str[i]-'a'];
if(index<0||i-index>curlength)
++curlength;
else
{
if(curlength>maxlength)
maxlength=curlength;
curlength=i-index;
}
position[str[i]-'a']=i;//更新字符出现的位置
if(curlength>maxlength)
maxlength=curlength;
delete[] position;
return maxlength;
}