此题坑我啊,看了我上一篇转载的博客后,是有点思路了,但是尝试了写了后总是有一些情况没有考虑清楚。后来就直接把别人的答案看了看,也算看懂了吧,此处就写写别人是怎么实现的。
首先变量说明:
1、cur表示搜索到当前字符时,无重复子串的个数。例如:
2、数组dp。dp[i]用来记录第i个字符,字符串长度。例如,搜索完毕的时候,dp数组的赋值如下,所以dp的长度与字符串长度相同。
3、bool变量norepeat,如果没有重复字符,则其为1,否则为0.
算法步骤:
1、如果字符串的长度length小于2,则直接返回字符串的长度。
2、开辟length长度的整形数组dp.
3、赋初值,maxlen=1,dp[0]=1(s[0]的当前字符串长度为1),接着从1开始搜索。
4、开始搜索
然后(i=2,j从i-1开始搜索,直到i - dp[i - 1],如果有重复则停止),j=1时,重复,停止
.........
如此一直往前搜索,其实j就是检验当前串s[i - dp[i - 1]]到s[i-1]是否有字符s[i]
如果有,表示重复了,则noRepeat=0,当前无重复子串cur也变化了,值为i-j-1.
如果没有重复,则是s[i-1]的无重复子串的数目+1.
最后比较当前dp[i]与maxlen的大小,将大的一个保存到maxlen中。
代码如下:
// test3LongestSubstring.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int lengthOfLongestSubstring(string s);
int max(int x, int y);
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "please input the string" << std::endl;
string str;
std::cin >> str;
int res = lengthOfLongestSubstring(str);
return 0;
}
int max(int x, int y)
{
if (x < y)
return y;
else
{
return x;
}
}
/*
dp[i]记录第i个字符的当前字符的无重复子串长度。
i作为头指针一直往前扫描。
然后j从i左边第一个起往左扫描当前字符串。如果发现当前字符串中包括s[i],则表明重复了,curlen应该变化为i-j-1,表示重复了。
扫描完当前字符串事,如果发现确实S[i]没有重复,则当前长度加1,如果发现重复了,则当前长度应该等于curLen+1
比较maxLen与dp[i]的值,maxLen取更大的那个
*/
int lengthOfLongestSubstring(string s) {
int length = s.length();
if (length < 2) return length;
int *dp = new int[length];
int maxLen = 1;
dp[0] = 1;
for (int i = 1; i < length; i++)
{
int curLen = 0;
bool noRepeat = true;
for (int j = i - 1; j >= i - dp[i - 1]; j--)
{
if (s[j] == s[i])
{
curLen = i - j - 1;
noRepeat = false;
break;
}
}
if (noRepeat)
dp[i] = dp[i - 1] + 1;
else
dp[i] = curLen + 1;
maxLen = max(maxLen, dp[i]);
}
//cout << maxLen << endl;
return maxLen;
}