传送门
考虑当前位于第
i
i
i位,如何让该位的字母最小,假设
1
∼
i
−
1
1\sim i-1
1∼i−1的字母已经固定并且无法在再改变,而第
i
+
1
∼
n
i+1\sim n
i+1∼n位的字母和顺序都还未被改变,第
i
i
i位上的字母可能被改变,也可能没有被改变,令
f
g
fg
fg为
1
1
1表示未被改变,也就是说在该位置上还有一次操作可使用,否则代表被改变,即第
i
i
i位不具有操作可用。
设 f ( c ) f(c) f(c)表示字母 c c c经过 u p / d o w n / 0 up/down/0 up/down/0操作后可以变成的最小字母(若 f g = 0 fg=0 fg=0那么 f ( c ) = c f(c)=c f(c)=c),特别地有 f ( ′ a ′ ) = ′ a ′ f('a')='a' f(′a′)=′a′。那么第 i i i位的字母只可能是 f ( s [ i ] ) , f ( s [ i + 1 ] ) , s [ i + 2 ] f(s[i]),f(s[i+1]),s[i+2] f(s[i]),f(s[i+1]),s[i+2]其中一个( s [ i + 3 ] s[i+3] s[i+3]必不可能到达第 i i i位)。
- 若 s [ i + 2 ] < m i n { f ( s [ i ] ) , f ( s [ i + 1 ] ) } s[i+2]<min\{f(s[i]),f(s[i+1])\} s[i+2]<min{f(s[i]),f(s[i+1])},我们就把 s [ i + 2 ] s[i+2] s[i+2]移动到当前位置。具体来说,经过三次操作后则我们能得到 i , i + 1 , i + 2 i,i+1,i+2 i,i+1,i+2位置上的字母为 s [ i + 2 ] , f ( s [ i ] ) , s [ i + 1 ] s[i+2],f(s[i]),s[i+1] s[i+2],f(s[i]),s[i+1]、。此时第 i + 1 , i + 2 i+1,i+2 i+1,i+2位置上的操作次数已经被消耗, i + 1 i+1 i+1位置上的字母无法被改变,因此我们跳过 i + 1 i+1 i+1位置到达 i + 2 i+2 i+2位置考虑第 i + 2 i+2 i+2位上的字母可以最小是多少,此时要设置 f g = 0 fg=0 fg=0。
- 若 f ( s [ i + 1 ] ) < f ( s [ i ] ) f(s[i+1])<f(s[i]) f(s[i+1])<f(s[i])且条件一不被满足,那么我们把 f ( s [ i + 1 ] ) f(s[i+1]) f(s[i+1])移动到当前位置,不过需要注意的是,当 f g = 0 fg=0 fg=0的时候,意味着 s [ i ] s[i] s[i]无法移动到第 i + 1 i+1 i+1位,因此只能 s [ i + 1 ] s[i+1] s[i+1]移动过来,这样的话 s [ i + 1 ] s[i+1] s[i+1]无法变成 f ( s [ i + 1 ] ) f(s[i+1]) f(s[i+1]),不过即使这样最坏情况也是两者相等,所以不影响结果,因此我们让 s [ i + 1 ] s[i+1] s[i+1]移动到第 i i i位,根据 f g = 0 fg=0 fg=0还是 f g = 1 fg=1 fg=1选择 s [ i ] = s [ i + 1 ] o r f ( s [ i + 1 ] ) s[i]=s[i+1]\,or\,f(s[i+1]) s[i]=s[i+1]orf(s[i+1])即可, s [ i + 1 ] s[i+1] s[i+1]也根据 f g = 0 fg=0 fg=0或 f g = 1 fg=1 fg=1进行相应地设置即可,不过设置完后仍然要让 f g = 0 fg=0 fg=0,因为第 i + 1 i+1 i+1位的操作是左移,已经将操作次数消耗完了。
- 如果上述两种情况都不满足,那么让 s [ i ] = f ( s [ i ] ) s[i]=f(s[i]) s[i]=f(s[i])即可,此时设置 f g = 1 fg=1 fg=1然后考虑下一位的情况即可。
char s[maxn],ans[maxn];
int k,n;
char f(char c){
if(c-'a'+1==k || c-'a'==0)return 'a';
return c-1;
}
int main(){
int t=rd();
while(t--){
n=rd(),k=rd();
rds(s+1);
s[n+1]='\0';
int tot=0,fg=1;
FOR(i,1,n){
char a=fg?f(s[i]):s[i];
char b=fg?f(s[i+1]):s[i+1];
fg=0;
if(i+2<=n && min(a,b)>s[i+2]){
ans[tot++]=s[i+2];
ans[tot++]=a;
s[i+2]=s[i+1];
i++;
}else if(b<a){
ans[tot++]=b;
s[i+1]=b==s[i+1]?a:s[i];
}else {
ans[tot++]=a;
fg=1;
}
}
ans[tot++]=fg?f(s[n]):s[n];
ans[tot]='\0';
wrsn(ans);
}
}