• 浅谈尺取法


    例题一:

    http://acm.hdu.edu.cn/showproblem.php?pid=5056

    题目大意翻译:

    给你一个由小写字母组成的字符串,使得子串中每个小写字母的数目不超过k,你的任务是计算这样的子串的数目

    分析:

    枚举字符串下标i,每次计算以i为结尾的符合条件的最长串。

    那么以i为结尾的符合条件子串个数就是最长串的长度。求和即可

    现在考虑如何算以i结尾的最长串

    好吧其实这就是个尺取法

    聪明的你一定看了code就会的

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int Max= 100010;
    char str[Max];
    int vis[30];
    int main()
    {
        int k,T,len;
        LL sum;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",str);
            scanf("%d",&k);
            memset(vis,0,sizeof(vis));
            len = strlen(str);
            int l=0;sum=0;
            for(int i=0;i<len;i++)
            {
                vis[str[i]-'a']++;
                while(vis[str[i]-'a']>k)vis[str[l]-'a']--,l++;
                sum+=(i-l+1);
    
            }
           cout<<sum<<endl;
        }
        return 0;
    }
    

    例题二:

    http://poj.org/problem?id=3061

    题目大意:给出一个序列,求区间和大于或者等于S的最短区间长度的最小值

    结合上一题,

    还是考虑以i结尾的区间和大于等于S的区间长度的最小值

    part code:

    for (int l=1,r=0,now=0;l<=n;){
      while (now<S&&r<n) now+=a[++r]; //表示先把r+1,再执行now+=a[r].注意要使r<=n.
      /*当now<S的时候,我们不断地向右延伸区间,直到now>=S*/
      if (now<S) break;
      /*这时候l已经过大了,r到n也满足不了条件,这时要退出循环,否则下面的ans会被错误更新.*/
      ans=min(ans,r-l+1); // [l,r]区间的长度
      now-=a[l++]; // 这里就是先执行now-=a[l],然后再执行l+=1.
    }
    

    例题三:

    https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=513&problem=2619&mosmsg=Submission+received+with+ID+11683193

    题目大意:题目要求找到一个尽量长的连续序列,使得该序列中没有相同的元素

    分析:

    从左到右首先尽量延长right,right无法延长时再继续把left向右移动一个,然后重复以上过程,每次再取ans最大值即可。另外再判断重复时可采用数据结构,利用set集合十分方便

    
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
     
    #define maxn 1000005
    int a[maxn];
    set<int> s;
     
    int main()
    {
    //	freopen("input.txt","r",stdin);
    	int t,n;
    	scanf("%d",&t);
    	while(t--){
    		s.clear();
    		scanf("%d",&n);
    		int i,l=0,r=0,ans=0;
    		for(int i=0;i<n;i++)
    		{
    			scanf("%d",&a[i]);
    		}
    		while(r<n){
    			while(r<n&&!s.count(a[r])) s.insert(a[r++]);
    			ans=max(ans,r-l);
    			s.erase(a[l++]);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    总之:

    尺取法很简单,处理一些不定区间或子集问题

  • 相关阅读:
    url
    松弛时间
    Linux下为当前用户添加 PYTHONPATH 环境变量
    ElasticSearch集群的安装(windows)
    软件开发安全
    java,判断手机设备跟adb建立连接
    question
    氚云后台代码小栗子,流程表单新增完成反写源单状态
    November Challenge 2020 Division 1
    February Challenge 2021 Division 1 选做
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11735405.html
Copyright © 2020-2023  润新知