//本题用动态规划求解,第一次完完全全按照自己思路实现,记录一下
// dp【n】设为以字符串第n个元素结尾的最长的子字符串
// 本题用hashMap<Character,Integer> 记录暂存的子字符串
// dp[n]的求解思路 循环遍历字符串
// 细分为 三种情况:
//一.当 第i个字符等于 第i-1 个字符时 --前面的字符串已经不能达到题目所给的要求,所以直接清除,长度置为1
//二、 当 第i个字符 不 等于 第i-1 个字符时,且map中不含该字符时,说明该字符在当前子字符串中无重复,直接加一
//方程:dp【i】 = dp【i-1】 + 1
//三、 当 第i个字符 不 等于 第i-1 个字符时,map中有该字符,即包含第i-1个字符的子字符串中 含有第i个元素
// 方程:dp【i】 = i- map.get(s.charAt(i));
//注意:以第i个字符结尾的情况中,可能以第i-1个字符结尾的子字符串也可能重复
//这个时候 方程: dp【i】应为 dp【i-1】 + 1
//综合两种情况,取最小值 ,因为小范围不成立大范围不可能成立
//状态转移方程代码如下:
import java.util.*;
public class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() < 1){
return 0;
}else if (s.length() ==1){
return 1;
}
// dp【n】设为以字符串第n个元素结尾的最长的子字符串
int[] dp = new int[s.length()];
//初始化
dp[0] = 1;
//暂存最大值dp【i】
int temp = 0;
int ans = 0;
//hashMap<Character,Integer> 记录暂存的子字符串
Map<Character,Integer> map = new HashMap<>();
//初始化
map.put(s.charAt(0),0);
for (int i = 1; i < s.length(); i++) { //遍历字符串
//当 第i个字符等于 第i-1 个字符时 前面的字符串已经不能达到题目所给的要求,所以直接清除,长度置为1
//然后以该字符开始新的子字符串
if (s.charAt(i) == s.charAt(i-1)){
map.clear();
dp[i] = 1;
map.put(s.charAt(i),i);
}
else{
//当map中不含该字符时,说明该字符在当前子字符串中无重复,直接加一
// dp【i】 = dp【i-1】 + 1
if (!map.containsKey(s.charAt(i))) {
dp[i] = dp[i - 1] + 1;
map.put(s.charAt(i),i);
}
//还有一种情况是map中有该字符,包含第i-1个字符的子字符串中含有第i个元素
//dp【i】 = i- map.get(s.charAt(i));
//注意:以第i个字符结尾的情况中,可能以第i-1个字符结尾的子字符串也可能重复
//这个时候dp【i】应为 dp【i-1】 + 1
//综合两种情况,取最小值
else {
dp[i] = Math.min(i - map.get(s.charAt(i)),dp[i-1] + 1) ;
map.replace(s.charAt(i),i);
}
}
if (dp[i] > temp){
temp = dp[i];
}
}
ans = temp;
return ans;
}
}