トピックの主なアイデア:長さnの文字列sが与えられた場合、文字列ansの文字数をmで割れるように、s以上の長さnの文字列ansを作成します。
アイデア:接尾辞付きの連続する文字の配列を作成(構築)します(後で判断時間を短縮するため)
dp [i] [j]は(dp [i] [j] -1) 'a' + j文字を表しますi番目の位置では、連続しています。
フラグを使用して、「文字列より大きい条件」が満たされているかどうかを示します
- 満足できない場合は、現在の位置に配置できる文字(現在の文字以上)を列挙し、まだ使用可能な文字があるかどうかを判断します(開くたびに文字を開くので、文字数はkで直接割ることができます)(1)利用可能な文字がない場合は、新しいkの文字グループを開き、(k-1)利用可能な場合、利用可能な合計数はkだけ減ります。次に、元の文字列よりも大きいかどうかを判断します。(2)入手可能な状態で使用してください。
- 満足した後、残っているものはすべて「a」になります。毎回kだから。したがって、残っているのもkの倍数です。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
char a[maxn];
int n,k,b[30],c[30],las[maxn][27],top;
char ans[maxn];
bool isok(int nxt,int c[]) {
while( nxt<=n ) {
for(int i='z'; i>='a'; i--) {
if( c[i-'a']==0 ) continue;///已满或者没有
if( i>a[nxt] ) return true;///已经比较大了
else if( i<a[nxt] ) return false;///当前位置比原小
else if( c[i-'a']>=las[nxt][i-'a'] ) {
///够后面用的 连续
c[i-'a'] -= las[nxt][i-'a'], nxt += las[nxt][i-'a'];
break;
} else if( c[i-'a']<las[nxt][i-'a'] ) return false;///不够
}
}
return true;//一直相等,也是合法的
}
int main() {
int t;
cin >> t;
while( t-- ) {
cin >> n >> k >> ( a+1 );
if( n%k!=0 ) {
cout << -1 << endl;
continue;
}
for(int i=n; i>=1; i--)
for(int j='a'; j<='z'; j++) {
if( a[i]==j ) las[i][j-'a'] = las[i+1][j-'a']+1;///后续连续字符
else las[i][j-'a'] = 0;
}
int flag = 1,sum = n;///flag来判断是否已经满足大于要求
for(int i=1; i<=n; i++) {
if( flag ) {
///未满足
for(char j=a[i]; j<='z'; j++) {
///枚举大于等于当前字符
if( b[j-'a'] ) {
///可用数量
memcpy( c,b,sizeof c );
c[j-'a']--;///放 j这个字符
c['z'-'a'] += sum;///剩下的都变成z字符
if( j>a[i] || isok(i+1,c) ) {
ans[i] = j;
b[j-'a']--;
if( j>a[i] ) flag = 0;
break;
}
} else {
if( sum<k ) continue;///剩下的不够新增字符的,
memcpy( c,b,sizeof c );
c[j-'a'] += k-1;
c['z'-'a'] += sum-k;///用最大的情况判断是否可行。
if( j>a[i] || isok(i+1,c) ) {
ans[i] = j;
sum -= k;
b[j-'a'] = k-1;
if( j>a[i] ) flag = 0;
break;
}
}
}
} else {
///字典序已经比较大了,后面怎样都无所谓,那么从'a'开始一直往后面放
b[0] += sum;
int id = i;
for(char j='a'; j<='z'; j++) while( b[j-'a'] ) ans[id++]=j, b[j-'a']--;
break;
}
}
for(int i=1; i<=n; i++) cout << ans[i];
cout << endl;
for(int i=1; i<=n; i++) memset( las[i],0,sizeof las[i] );
memset( b,0,sizeof b );
}
}