给定一个字符串,找到最长的子串,要求该子串中没有重复的字符。
例如:
字符串abcabcbb
的不含重复字符的 最长 子串为abc
,长度为 3。
而bbbbbb
的不含重复字符的 最长 子串为b
,长度为 1。
输入格式
输入包含多行,每一行对应一个长度不超过 100100 的输出,直到遇到结束符为止。每行依次输入字符串s
。
输出格式
输出不含重复字符的 最长 子串的长度。
样例输入
hchzvfrkmlnozjk
样例输出
11
#include<string>
#include<iostream>
using namespace std;
int abtno(char a)
{
switch(a){
case 'a': return 0;
case 'b': return 1;
case 'c': return 2;
case 'd': return 3;
case 'e': return 4;
case 'f': return 5;
case 'g': return 6;
case 'h': return 7;
case 'i': return 8;
case 'j': return 9;
case 'k': return 10;
case 'l': return 11;
case 'm': return 12;
case 'n': return 13;
case 'o': return 14;
case 'p': return 15;
case 'q': return 16;
case 'r': return 17;
case 's': return 18;
case 't': return 19;
case 'u': return 20;
case 'v': return 21;
case 'w': return 22;
case 'x': return 23;
case 'y': return 24;
case 'z': return 25;
}
}
int maxx(int a, int b){return a>b?a:b;}//求较大值函数
int main()
{
string str;
while(cin>>str){
int fre[26]={0};//将字母的频率初始化为0
int head=0,end=0;//队列的头、尾初始化为0
int max[100]={0};
int k=0;
int m=0;//记录max里面的最大值
while(end<str.size()){
fre[abtno(str[end])]++;//记录频率
if(fre[abtno(str[end])]!=1){//重复了
max[k++]=end-head;
while(str[head]!=str[end]){
fre[abtno(str[head])]--;
head++;
}
fre[abtno(str[head])]--;
head++;
}
end++;//新的元素入队
}
if(k==0){//没有重复的字母
cout<<str.size();
}
else{
max[k]=end-head;
for(int i=0;i<k+1;i++){
m=maxx(max[i],m);
}
cout<<m;
}
cout<<endl;
}
return 0;
}
思路:利用类似队列的思想,用head表示队头,end表示队尾,对字符串从前向后遍历,由end入队,入队的同时用hash的方式检查是否重复,若重复,则保存此时的子串长度,放入max数组,再由队头将元素一个一个出队,直到出队的元素就是那个重复的元素为止。若不重复,则没什么特殊处理。然后再由end入队,重复上述过程,直到end已经达到输入字符串的末尾为止。遍历结束后,在max数组里面找最大的子串长度,输出即可。
总结:
1、对于需要处理字符串的题目,直接使用c++风格的输入输出,同时c++的库里也有相应的字符串的函数,很方便
2、类似的,如果输入有多组,可以先写出一组,再写多组输入的处理
3、多想,多思考!代码不是关键的,关键的是代码的思路!