题意
给定一个字符串
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(0≤i<⌊2n+1⌋,其中 n n n 为字符串长度。因此我们依次枚举 i i i,并判断以下情况:
-
s
i
≠
s
n
−
i
−
1
s_i \not = s_{n - i - 1}
si=sn−i−1 且 两者都不为 ‘?’,输出
IMPOSSIBLE
。 -
s
i
≠
s
n
−
i
−
1
s_i \not = s_{n - i - 1}
si=sn−i−1 且其中一者为 ‘?’,将那一项变为不为
?
的那一项。
因为要求有
k
k
k 种字母,于是我们用
v
i
v_i
vi 统计每个字母出现的次数。如果
v
i
=
0
(
i
≤
k
)
v_i = 0 (i \leq k)
vi=0(i≤k),则
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
cnt←cnt+1,bcnt←bcnt+1。因为要求字典序最小,所以我们从字符串最中间向两边扩散,如果遇到 ?
就把 ?
改成
b
c
n
t
b_{cnt}
bcnt,同时
c
n
t
←
c
n
t
−
1
cnt \gets cnt - 1
cnt←cnt−1。如果
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;
}