题解:
考察点: 区间合并,双指针
方法一:暴力
一般来说,暴力都是解决问题最直观,也是最容易被同学们想到的方法。题中明确说明每个字母只能在一个子串中出现,因此必须保证子串内的每个字母在字符串中第一次出现的位置到最后一次出现的位置都位于区间中。设置两个指针和
,表示区间的开始位置和结束位置。当访问到字符串中位置
时,如果
不超过
,则比较在字符串中结束位置和
的大小,如果大于
,则把
修改为
的结束位置;如果
大于
,则记录区间
的长度。因为对于每个位置都需要向后找寻结束位置,一共有
个位置需要找寻,时间复杂度是
#include "bits/stdc++.h"
using namespace std;
string s;
int main()
{
cin>>s;
int len=s.length();
int Start=0,End=0;
for(int i=0;i<len;i++){
if(s[i]==s[0]) End=i;
}
vector<int>v;
for(int i=0;i<len;i++){
if(i<=End){
for(int j=i+1;j<len;j++){
if(s[i]==s[j]) End=max(End,j);
}
}else{
v.push_back(End-Start+1);
Start=i,End=i;
for(int j=i;j<len;j++){
if(s[j]==s[i]) End=j;
}
}
}
v.push_back(End-Start+1);
for(int i=0;i<v.size();i++){
if(i==v.size()-1) printf("%d\n",v[i]);
else printf("%d ",v[i]);
}
return 0;
} 方法二:区间合并
更进一步,可以对上述方法做出优化。设置两个数组和
,分别记录每个字母在字符串中的开始位置和结束位置。其余流程跟方法一相同,这样在维护每个字母的开始位置和结束位置时,不用对整个字符串做遍历,通过空间换时间的方法,将时间复杂度降到
#include "bits/stdc++.h"
using namespace std;
const int maxn=30;
int l[maxn],r[maxn];
string s;
int main()
{
memset(l,-1,sizeof(l));
memset(r,-1,sizeof(r));
cin>>s;
int len=s.length();
for(int i=0;i<len;i++){
int tmp=s[i]-'a';
if(l[tmp]==-1){
l[tmp]=i,r[tmp]=i;
}else{
r[tmp]=i;
}
}
int Start=l[s[0]-'a'],End=r[s[0]-'a'];
vector<int>v;
for(int i=0;i<len;i++){
int tmp=s[i]-'a';
if(i>End){
v.push_back(End-Start+1);
Start=i;
End=r[tmp];
}else{
End=max(End,r[tmp]);
}
}
v.push_back(End-Start+1);
for(int i=0;i<v.size();i++){
if(i==v.size()-1) printf("%d\n",v[i]);
else printf("%d ",v[i]);
}
return 0;
} 
京公网安备 11010502036488号