48 最长不含重复字符的子字符串

题目

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含′a′′a′~′z′′z′的字符。例如,在字符串"arabcacfr""arabcacfr"中,最长的不含重复字符的子字符串是"rabc""rabc"或者"acfr""acfr",长度为4。

AcWing OJ

C++ 题解

动态规划,用f(i)表示以i个字符结尾不包含重复子字符串的最长长度,从左向右扫描:

  • 若第i个字符在之前没出现过,则 f(i) = f(i-1) + 1;
  • 若第i个字符在之前出现过,计算第i个字符距离上次出现之间的距离为d:
    • 若d <= f(i-1),则说明第i个字符上次出现在f(i-1)对应的不重复字符串之内,那么这时候更新 f(i) = d
    • 若d > f(i-1),则无影响,f(i) = f(i-1) + 1

例如arabcacfr:

f(0) =1,  a
f(1) = 2,  ar
f(2) = 2,  ra,因为d=2,f(1)=2,所以上一个a在f(1)之中
f(3) = 3,  rab
f(4) = 4,  rabc
f(5) = 3,  bca,因为d=3,f(1)=4,所以上一个a一定在f(4)中
f(6) = 2,  ac
f(7) = 3,  acf
f(8) = 4,  acfr,因为d=7,f(7)=3,因此上一个r不在f(7)中,f(8) = f(7) + 1
int longestSubstringWithoutDuplication(const std::string& str)
{
	int curLength = 0;
	int maxLength = 0;

	//存放26个英文字符的数组,初始化为-1,表示该字符还没有出现过
	int* position = new int[26];
	for (int i = 0; i < 26; ++i)
		position[i] = -1;

	for (int i = 0; i < str.length(); ++i)
	{
		int prevIndex = position[str[i] - 'a'];

		// 该字符没有出现过,或者是d>f(i-1)
		if (prevIndex < 0 || i - prevIndex > curLength)
			++curLength;
		// 该字符出现过
		else
		{
			if (curLength > maxLength)
				maxLength = curLength;
			// f(i) = d
			curLength = i - prevIndex;
		}
		position[str[i] - 'a'] = i;
	}

	if (curLength > maxLength)
		maxLength = curLength;

	delete[] position;
	return maxLength;
}

python 题解

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start=0
        maxLength=0
        usedChar={}
        for i in range(len(s)):
            if s[i] in usedChar and start<=usedChar[s[i]]:
                start=usedChar[s[i]]+1
            else:
                maxLength=max(maxLength,i-start+1)
            usedChar[s[i]]=i
        
        return maxLength
posted @ 2019-03-16 20:08  youngliu91  阅读(153)  评论(0编辑  收藏  举报