计蒜客 最长不重复子串

题干:

给定一个字符串,找到最长的子串,要求该子串中没有重复的字符。

例如:

字符串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);
	}
	}

}

点赞