C1000 完美子串题解
Description
非常喜欢完美的字符串,当然,一个完美的字符串一定是简约并且多样的。现在 有一个字符串,他想知道这个字符串的完美子串的最小长度是多少。
一个完美子串,是原串的一个连续子序列,并且包含了不同的 个大写字
母。
当然了如果 的字符串中并不存在完美子串,则输出 。
设字符串长度为 。
40pts
先考虑最暴力的暴力,枚举一个长度 ,然后从左往右做一个“滑动窗口”,动态维护一个 大小的桶即可。如果一旦发现合法位置,输出当前的 并退出程序即可。时间复杂度 。
100pts
转换一下暴力,改为枚举一个右端点 ,然后从 开始往左扫,一旦发现已经扫过的区域内包含了所有字母,就把 取 然后 。最后输出 即可。
显然这样做没有优化时间复杂度,非常容易被卡到 。但我们发现,假设当前的右端点为 ,那我们在右端点为 时已经扫出了一段合法的区间,这段区间完全可以现在继续使用,而不是扔掉不管。
想象现在我们有一段包含 个英文字母的合法区间,往右“添加”一个字母,肯定不会让这个区间变得不合法。于是我们就成功地把 时找到的区间转移给了 。但这样有可能不是最优。也许在向右“添加”后,左侧可以“吐出”一个字母,且保证区间合法。
所以用双指针做即可。每次让右端点 ,然后维护左端点,取 即可。注意边界情况。
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define INF 0x7fffffff
#define MAXN 2000005
#define eps 1e-9
#define foru(a,b,c) for(int a=b;a<=c;a++)
#define RT return 0;
#define db(x) cout<<endl<<x<<endl;
#define LL long long
#define int LL
#define LXF int
#define RIN rin()
#define HH printf("\n")
using namespace std;
inline LXF rin(){
LXF x=0,w=1;
char ch=0;
while(ch<'0'||ch>'9'){
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
return x*w;
}
string s;
int v[500],tot;
signed main(){
cin>>s;
int n=s.size();
int l=0,r=0;
v[s[0]]++;
tot++;
int ans=INF;
while(1){
if(tot==26){
ans=min(ans,r-l+1);
}
if(r<=s.size()-2){
r++;
v[s[r]]++;
if(v[s[r]]==1) tot++;
}
if(tot==26){
ans=min(ans,r-l+1);
}
while(l<r){
if(v[s[l]]==1) break;
v[s[l]]--;
l++;
}
if(tot==26){
ans=min(ans,r-l+1);
}
if(r==s.size()-1){
while(l<r && tot==26){
ans=min(ans,r-l+1);
v[s[l]]--;
if(v[s[l]]==0) tot--;
}
break;
}
}
if(ans!=INF) cout<<ans;
else cout<<"QwQ";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步