[codeforces 1354B] Ternary String 寻找6种组合

本文详细解析了CodeforcesRound87中的B题“TernaryString”,介绍了寻找六种特定字符组合的算法思路及实现代码,同时对比了AtCoder与Codeforces的题目难度。

Educational Codeforces Round 87 (Rated for Div. 2)  参与排名人数11499,比赛前遇到2次延时,17:05-17:15,17:15-17:20

[codeforces 1354B]   Ternary String   寻找6种组合

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1354/problem/B

ProblemLangVerdictTimeMemory
B - Ternary String GNU C++17Accepted31 ms8500 KB

没想到AtCoder的D题难度,CodeForces曾经的E题,D题难度出现在B题,一下有些接受不了。

调整了一下,进行编码,虽说思路是现成的,但编码加调试,也花了不少时间。

思路如下:

共有6种组合(213,312,123,321,132,231)

对字符的数组进行遍历,

会遇到三种字符1,2,3

若遇到颜色1,会遇到两种组合,213,312,注意,让遇到的这个位置的字符1,充当中间位置的字符。

如213,可找到离该位置最近的左侧字符2的位置,可找到离该位置最近的右侧字符3的位置,

根据字符3与字符2间距,找最小值。

若遇到字符2,思路如上。

若遇到字符3,思路如上。

若觉得文字理解不了,请看如下模拟

112233

4

位置1    2    3    4    5    6  
数值1    1    2    2    3    3
读到位置1(对应字符1):左边找不到其它字符,此组数据无效

读到位置2(对应字符1):左边找不到其它字符,此组数据无效

读到位置3(对应字符2):
左边找到最近的字符1(位置2),右边找到最近的字符3(位置5),该组组合123,对应位置(2,3,5)
值5-2+1=4

读到位置4(对应字符2):
左边找到最近的字符1(位置2),右边找到最近的字符3(位置5),该组组合123,对应位置(2,4,5)
值5-2+1=4

读到位置5(对应字符3):
右边找不到其它字符,此组数据无效

读到位置6(对应字符3):
右边找不到其它字符,此组数据无效

在上述值中,取最小值4

AC代码如下

#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 200010
using namespace std;
char s[maxn];
int a1[maxn],b1[maxn],c1[maxn],a2[maxn],b2[maxn],c2[maxn],mn;
int main(){
	int t,n,i;
	scanf("%d",&t);
	while(t--){
		scanf("%s",s+1);
		n=strlen(s+1),mn=maxn;
		for(i=0;i<=n;i++)a1[i]=b1[i]=c1[i]=0;//初始化
		for(i=1;i<=n+1;i++)a2[i]=b2[i]=c2[i]=n+1;//初始化
		for(i=1;i<=n;i++)
			if(s[i]=='1')a1[i]=i,b1[i]=b1[i-1],c1[i]=c1[i-1];//a1[i]记录左边离i位置最近的字符1的位置(包括了i位置)
			else if(s[i]=='2')b1[i]=i,a1[i]=a1[i-1],c1[i]=c1[i-1];//b1[i]记录左边离i位置最近的字符2的位置(包括了i位置)
			else if(s[i]=='3')c1[i]=i,a1[i]=a1[i-1],b1[i]=b1[i-1];//c1[i]记录左边离i位置最近的字符3的位置(包括了i位置)
		for(i=n;i>=1;i--)
			if(s[i]=='1')a2[i]=i,b2[i]=b2[i+1],c2[i]=c2[i+1];//a2[i]记录右边离i位置最近的字符1的位置(包括了i位置)
			else if(s[i]=='2')b2[i]=i,a2[i]=a2[i+1],c2[i]=c2[i+1];//b2[i]记录右边离i位置最近的字符2的位置(包括了i位置)
			else if(s[i]=='3')c2[i]=i,a2[i]=a2[i+1],b2[i]=b2[i+1];//c2[i]记录右边离i位置最近的字符3的位置(包括了i位置)
		if(!a1[n]||!b1[n]||!c1[n]){printf("0\n");continue;}//1,2,3字符有缺失
		for(i=1;i<=n;i++){//i代表所要寻找的中间位置
			if(s[i]=='1'){
				if(b1[i]>0&&c2[i]<n+1)mn=min(mn,c2[i]-b1[i]+1);//213
				if(c1[i]>0&&b2[i]<n+1)mn=min(mn,b2[i]-c1[i]+1);//312
			}else if(s[i]=='2'){
				if(a1[i]>0&&c2[i]<n+1)mn=min(mn,c2[i]-a1[i]+1);//123
				if(c1[i]>0&&a2[i]<n+1)mn=min(mn,a2[i]-c1[i]+1);//321
			}else if(s[i]=='3'){
				if(a1[i]>0&&b2[i]<n+1)mn=min(mn,b2[i]-a1[i]+1);//132
				if(b1[i]>0&&a2[i]<n+1)mn=min(mn,a2[i]-b1[i]+1);//231
			}
		}
		printf("%d\n",mn);
	}
}

类似题目:

[codeforces 1337D] Xenia and Colorful Gems 寻找6种组合

AtCoder Beginner Contest 162 D RGB Triplets 前缀和

[codeforces 1335E1] Three Blocks Palindrome (easy version) 分成左中右3个区间+前缀和

[codeforces 1335E2] Three Blocks Palindrome (hard version) 从中间位置向两边扩散

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值