CF59C 题解

题意

给定一个字符串 s s s 与长度 k k k,其中 s s s 会有一些字符是 ?,问是否能够通过将 ? 改成其他字符的形式,达成 s 是回文串,且第 1 1 1 到第 k k k 个英文小写字母都有用到。如果可以,输出字典序最小的那个,否则输出 IMPOSSIBLE

思路

显而易见,因为要求是回文串,所以对于所有的 i ( 0 ≤ i < ⌊ n + 1 2 ⌋ i(0 \leq i < \lfloor \dfrac{n + 1}{2} \rfloor i(0i<2n+1,其中 n n n 为字符串长度。因此我们依次枚举 i i i,并判断以下情况:

  • s i ≠ s n − i − 1 s_i \not = s_{n - i - 1} si=sni1 且 两者都不为 ‘?’,输出 IMPOSSIBLE
  • s i ≠ s n − i − 1 s_i \not = s_{n - i - 1} si=sni1 且其中一者为 ‘?’,将那一项变为不为 ? 的那一项。

因为要求有 k k k 种字母,于是我们用 v i v_i vi 统计每个字母出现的次数。如果 v i = 0 ( i ≤ k ) v_i = 0 (i \leq k) vi=0ik,则 c n t ← c n t + 1 , b c n t ← b c n t + 1 cnt \gets cnt + 1,b_{cnt} \gets b_{cnt} + 1 cntcnt+1,bcntbcnt+1。因为要求字典序最小,所以我们从字符串最中间向两边扩散,如果遇到 ? 就把 ? 改成 b c n t b_{cnt} bcnt,同时 c n t ← c n t − 1 cnt \gets cnt - 1 cntcnt1。如果 c n t = 0 cnt = 0 cnt=0 时改成 ‘a’ 即可。最后判断 c n t ≠ 0 cnt \not = 0 cnt=0,输出即可。

代码

#include<bits/stdc++.h>
using namespace std;
int k;
string a;
int v[27],b[27],cnt = 0;
int main() {
	cin >> k >> a;
	int n = a.size();
	for(int i = 0;i < (n + 1) / 2;i++) {
		//printf("%d %d %d\n",n,i,n - i - 1);
		if(a[i] != a[n - i - 1]) {
			if(a[i] == '?') a[i] = a[n - i - 1];
			else if(a[n - i - 1] == '?') a[n - i - 1] = a[i];
			else {
				printf("IMPOSSIBLE\n");
				return 0;
			}
		}
		if(a[i] >= 'a' and a[i] <= 'z')v[int(a[i] - 'a') + 1]++;

	}
	for(int i = 1;i <= k;i++) {
		if(v[i] == 0) b[++cnt] = i;
		//printf("%d ",v[i]);
	}
	//printf("\n");
	for(int i = (n + 1) / 2 - 1;i >= 0;i--) {
		//printf("%d %d\n",i,cnt);
		if(a[i] == '?') {
			if(cnt) {
				a[i] = char(b[cnt--] - 1) + 'a';
				a[n - i - 1] = a[i];
			}
			else a[i] = 'a',a[n - i - 1] = 'a';
		}
	}
	if(cnt) 	printf("IMPOSSIBLE\n");
	else cout<<a<<endl;
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值