# 说到【最长】第一想法就是动规;【去重复】第一想法就是哈希
# 题目:无重复的子序列长度
# 
# @param arr int整型一维数组 the array
# @return int整型
#
class Solution:
    def maxLength(self , arr ):
        # write code here
        """
        # 状态定义:以arr[i]结尾的最长子串长度为dp[i]
        dp = [1] + [0] * (len(arr)-1)
        mark = 0 # 寻找最长子串的开头位置
        # 遍历整个串
        for i,s in enumerate(arr):
            for j in range(mark, i):
                if s == arr[mark]:
                    mark = j + 1 # mark 是从上一个状态开始变的,不用从头考虑
                dp[i] = i - mark + 1
        return max(dp)
        """
        dic = {}
        res = tmp = 0
        for j in range(len(arr)):
            i = dic.get(arr[j], -1)
            dic[arr[j]] = j
            tmp = j - i if tmp >= j - i else tmp + 1
            res = max(res, tmp)
        return res          
# 题目分析:
# 长度为n的字符串共有n(n+1)/2个子字符串(复杂度为O(n^2)
# 判断长度为n的字符串是否有重复字符的复杂度为O(n)
# 因此本题使用暴力法解决的复杂度为O(n^3)
#
# 状态定义:dp[i]表示以str[i]结尾的最长不重复子串的个数
# 状态转移:添加新字符,dp[]
# 状态初始化:dp[0]=1
# 是否包含重复字符如何判断?选择使用两个下标变量表示
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        dp, j = [1] + [0] * (len(s) - 1), 0  # 用于比较i之前的元素是否与i所指元素一致
        if s == '':
            return 0
        for i in range(1, len(s)):
            # 每新加一个字符,就需要判断该字符是否在s[j:i]中包含,若不包含j不变,若包含j,那么j移动到下一个字符
            for k in range(j, i):
                if s[i] == s[k]: j = k + 1
            dp[i] = i - j + 1
            print(i, j, dp)
        return max(dp)


# 虽然解出来了,但是没有找到状态转移公式:dp[i]=dp[i-1]+1 if dp[i-1]<j-i else i-j
# 并且时间复杂度为O(n^2),空间复杂度O(n)可以用tmp来降低
# 本题比较关键的点就是找前面子串中是否出现过当前字符,并且找出该字符的位置。(我的方式时遍历前面的子串)

# 可以通过哈希表来存储各个字符出现最后一次的位置
class Solution1:
    def lengthOfLongestSubstring(self, s: str) -> int:
        dic = {}  # 用于寻找重复出现的字符
        res = tmp = 0  # 取代dp数组造成的空间复杂度
        for j in range(len(s)):  # 右边界(新添字符位置)
            i = dic.get(s[j], -1)  # 获取左边界i
            dic[s[j]] = j  # 更新哈希表
            tmp = tmp + 1 if tmp < j - i else j - i  # 状态转移
            res = max(res, tmp)
        return res


print(Solution1().lengthOfLongestSubstring('abcabcbb'))