CodeForces - 701C They Are Everywhere (尺取法)

本博客介绍如何使用尺取法解决编程问题,具体是寻找一个包含给定字符串中所有字符的最短连续子串。通过移动开始点和结束点来检查子串是否符合条件,确保每个点最多被访问两次,实现O(n)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

题意:

        给你一个长度为N的串,求最短连续子串的长度。子串要包含原串所有字母。(本题只包含大小写字母)

思路:

        这是一道尺取法的典型例题,通过开始点和结束点的移动取得子串,并判断是否符合题意。每个点只会被访问两次,时间复杂度为O(n)。

        注:尺取的规则是

                          1.若子串不符合条件,则子串向右扩张,向右移动结束点。

                          2.若子串符合条件,则子串向左收缩,向右移动开始点。

代码:

#include <bits/stdc++.h>

using namespace std;
int cut[150];
bool a[150];
int n,st,en,ans,all,sum;
string str;
void st_shift(){
    if(cut[str[st]]==1) sum-=str[st];
    cut[str[st]]--;
    st++;
    return ;
}
void en_shift(){
    en++;
    if(cut[str[en]]==0) sum+=str[en];
    cut[str[en]]++;
    return ;
}
int main()
{
    while(cin>>n>>str){
        sum=st=en=all=0;ans=n;
        memset(cut,0,sizeof(cut));
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
            if(!a[str[i]]){
                all+=str[i];
                a[str[i]]=1;
            }
        sum=str[0];
        cut[str[0]]++;
        while(en<n){
            if(sum==all){
                ans=min(ans,en-st+1);
                st_shift();
            }else{
                en_shift();
            }
        }
        cout<<ans<<endl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值