zoukankan      html  css  js  c++  java
  • 51nod-1127 最短的包含字符串(尺取法)

    1127 最短的包含字符串

    给出一个字符串,求该字符串的一个子串s,s包含A-Z中的全部字母,并且s是所有符合条件的子串中最短的,输出s的长度。如果给出的字符串中并不包括A-Z中的全部字母,则输出No Solution。
    输入
    第1行,1个字符串。字符串的长度 <= 100000。
    输出
    输出包含A-Z的最短子串s的长度。如果没有符合条件的子串,则输出No Solution。
    输入样例
    BVCABCDEFFGHIJKLMMNOPQRSTUVWXZYZZ
    输出样例
    28
    本题要求输出A-Z的最短区间子串s的长度,可以使用尺取法(即双指针)法写题,该算法的复杂度是O(n),尺取法即设置两个变量指向一前一后,遍历数组即可,贴AC代码

    #include <bits/stdc++.h>
    using namespace std;
    string str;
    int cnt[30];
    const int _max=1e5+5;
    int main()
    {
    	int start=0,t=0;
    	int ans=_max;
    	cin>>str;
    	memset(cnt,0,sizeof(cnt));
    	for(int i=0;i<str.length();i++)
    	{
    		int c=str[i]-'A';
    		if(!cnt[c])
    		  t++;
    		cnt[c]++;
    		while(cnt[str[start]-'A']>1)
    		  cnt[str[start]-'A']--,start++;
    		if(t==26)
    		  ans=min(ans,i-start+1);  
    	}
    	if(t<26)
    	  cout<<"No Solution"<<endl;
    	else
    	  cout<<ans<<endl;
    	return 0;  
    }
    

    题解:开始定义start,即后面的指针,t=0,t是区间长度的计数器,ans是区间长度,也就是答案,因为要对ans和长度取最小值,所以一开始ans直接设max,cnt即计数器数组,他的下标0-25记录的是字母A-Z出现的次数,首先将cnt数组全部置0,输入字符串。在for循环中,刚开始的cnt计数器数组,如果cnt[i]的值为0,就说明编号为i+1的字母没出现过,t++,并且当前的编号为i+1的下标加一,当走到第一while语句时,开始判断start,即第一个指针,cnt数组中start指向的元素是不是出现了一次以上,如果是,则cnt[str[start]-‘A’]减一,并且指针后移,走到 i f 时,判断26个字母是不是都出现过了,如果都出现过,则开始取ans和区间长度(i-start+1)的最小值。退出循环,若t<26,则说明26个字母没有都出现过,输出No Solution,反之输出ans。

  • 相关阅读:
    Java版AES-CBC-CMAC加密
    并发编程(十九):并发编程实践
    并发编程(十八):ScheduledThreadPoolExcutor和FutureTask
    并发编程(十七):Excutor与ThreadPoolExcutor
    并发编程(十六):线程池概述
    并发编程(十五):Java并发工具类
    并发编程(十四):原子操作类
    并发编程(十三):Fork-Join框架
    并发编程(十二):阻塞队列
    并发编程(十一):非阻塞队列ConcurrentLinkedQueue
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294335.html
Copyright © 2011-2022 走看看