题干:
给定一个字符串,找到最长的子串,要求该子串中没有重复的字符。
例如:
字符串abcabcbb
的不含重复字符的 最长 子串为abc
,长度为 3。
而bbbbbb
的不含重复字符的 最长 子串为b
,长度为 1。
输入格式
输入包含多行,每一行对应一个长度不超过 100100100 的输出,直到遇到结束符为止。每行依次输入字符串s
。
输出格式
输出不含重复字符的 最长 子串的长度。
这里先排坑:
1、输出为多行,所以要使用一个hasnext()判断输入是否结束
2、暂定输入只有26个小写字母
3、采用动态规划+hash的算法
思路:
定义一个数组ans[],元素为以当前字符为最后一个字符的子串的长度,初始化为0,ans[0]=1。
hash数组hash[],value值为元素在字符串中的位置i。元素初始化为-1,第一个元素的hash为0。
一个标记last_start:记录当前子串的起始位置—非常有用!通过判定last_start和hash重复出现字符的位置可以确认是否真的冲突了(因为字符可以出现多次,只要当前子串中没有即可)
import java.util.*;
public class jsk {
public static void main(String[] arg)
{
Scanner in=new Scanner(System.in);
while(in.hasNext())
{
String a=in.nextLine();
int []hash=new int[26];
for(int i=0;i<26;i++)
hash[i]=-1;
char[] s=a.toCharArray();
int l=s.length;
int []ans=new int[l]; //以该字符为最后一个字符的子串长度
hash[s[0]-'a']=0;
ans[0]=1;
int last_start=0;
for(int i=1;i<=l-1;i++)
{
int x=s[i]-'a';
if(hash[x]==-1)
{
hash[x]=i; //哈希value值为 字符在数组的位置
ans[i]=ans[i-1]+1; //第一次遇到这个字符 加入子序列 长度加1
}
else {
if(hash[x]>=last_start) //当前子串的起点在冲突字符前,需要截断。
{
ans[i]=i-hash[x];
last_start=hash[x]+1;
hash[x]=i;
}
else{
ans[i]=ans[i-1]+1;//未冲突,但是已经遍历过这个字符
hash[x]=i;
}
}
}
int answer=0;
for(int i=0;i<l;i++)
{
if(ans[i]>answer)
answer=ans[i];
}
System.out.println(answer);
}
}
}