题解 CF1354B 【Ternary String】

题意

给出一个字符串,只包含 \({1,2}\)\({3}\) 。从中找出一个长度最短的子串,要求至少包含 \({1,2,3}\) 各一次,并输出其长度。

输入格式

本题有多组测试数据

第一行一个整数 \(t\) ,表示数据组数

接下来 \({t}\) 行,每行一个字符串 \(s\) ,它的每个字符只可能是 \(1,2\)\(3\)\({s}\) 的长度不超过\(200000\)

输出格式

对于每组数据,输出一行一个整数,表示最短的符合要求的子串的长度。如果不存在,输出 \(0\)

说明与提示

\(1 \le t \le20000\)
\(1 \le |s| \le 200000\)

Solution

我们可以开一个数组 $a $ ,其中 \(a_i\) 表示 i 上次出现的位置($ 1\le i \le 3$ ),初始时,\(a_i=-1\)

然后线性扫过去,不断更新 \(a\),当停留在第 $ k $位时, a[ s[k]-'0' ]= k 。 显然,以第 \(k\) 位结尾的符合要求的子串长度为 k-min(a[1],a[2],a[3])+1 。此时我们可以更新 \(ans\)

代码 ↓

注意多测

#include<bits/stdc++.h>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
const int MAXN=200010;
int t,a[5],ans=MAXN;
int main (){
	scanf("%d",&t);
	while(t--){
		string s;
		cin>>s;
		a[1]=-1;a[2]=-1;a[3]=-1;ans=MAXN;
		int ls=s.length();
		for(int i=0;i<ls;i++){
			a[s[i]-'0']=i;
			int minn=MAXN;
			for(int j=1;j<=3;j++){
				minn=min(minn,a[j]);	
			}
			if(minn==-1)continue;
			ans=min(ans,i-minn+1);
			if(ans==3)break;
		}
		if(ans==MAXN)printf("0\n");
		else printf("%d\n",ans);
	}
	return 0;
}

本蒟蒻第一次写题解,巨佬轻喷

posted @ 2020-06-07 09:11  Werner_Yin  阅读(223)  评论(0编辑  收藏  举报