题目:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
程序设计如下:
采用滑动窗口思想,建立一个list(窗口),将字符串一个一个从尾部压入,每压入一个元素都要检查窗口内是否有重复的元素,如果没有则继续压入新元素;如果有,则从链表头部弹出一个元素,保持窗口大小不变。
显而易见,当窗口里有重复元素时,窗口大小保持不变;窗口没有重复元素时,不断压入新元素。因此窗口大小就是最长子串的长度。
#include <iostream>
#include <list>
#include <string>
#include <iterator>
using namespace std;
class Lngst_substring
{
public:
bool input();//输入字符串
bool sliding_window();//滑动窗口查找最长子串
bool output();//输出查找的子字符串
private:
string input_str;
list<char> sliding_str;
};
bool Lngst_substring::input()
{
cout<<"请输入一个字符串:"<<endl;
cin>>input_str;
cout<<"所有可能的无重复子串:"<<endl;
return true;
}
bool Lngst_substring::sliding_window()
{
int flag=0;//跳出循环标志
int temp=0;//存放窗口大小
for(int i=0;i<input_str.length();i++)//将string按位从尾部压入滑动窗口
{
sliding_str.push_back(input_str[i]);
for(list<char>::iterator current_it=sliding_str.begin();current_it!=sliding_str.end();current_it++)//查看滑动窗口内是否有重复元素,如果没有继续压入元素//如果有,则从链表头部弹出一个元素,然后在压入
{
list<char>::iterator next_it=current_it;
next_it++;
for(;next_it!=sliding_str.end();next_it++)
{
if(*current_it==*next_it)
{
sliding_str.pop_front();
flag=1;
break;
}
}
if(flag==1)
{
flag=0;
break;
}
}
if(temp<sliding_str.size()) //窗口每次增长都会打印一次数据,不增长则意味着里面有重复子串,则不打印
{
for(list<char>::iterator it=sliding_str.begin();it!=sliding_str.end();it++)
{
cout<<*it;
}
temp=sliding_str.size();
cout<<endl;
}
}
return true;
}
bool Lngst_substring::output()
{
cout<<endl<<"最长子串长度为:"<<endl;
cout<<sliding_str.size()<<endl;
return true;
}
int main()
{
Lngst_substring substring;
substring.input();
substring.sliding_window();
substring.output();
system("pause");
return true;
}
调试结果如下: