rt,主要思路是先按字典序从小到大排序,然后找到字典序最小的字符串和所有以它为前缀的字符串。
依次比较在重复多次的时候哪个字符串最小。
对于最小的字符串,找到和它比较的字符串在前缀出现了几次(如 cb 在 cbcbcba 的前缀出现了 3 次)。然后如果剩余没输出的次数 k′ 比这个次数小,就跳到这个字符串。
写完错了 10 个点,不知道是代码写挂了还是做法假了。
可能说得有点不太清楚。
::::info[代码]
#include<bits/stdc++.h>
#define ll long long
#define re register
#define fi first
#define se second
using namespace std;
inline ll read(){
ll res=0ll,f=1;
char c;
for(;(c=getchar())<'0'||c>'9';c=='-'?f=-f:0);
while(c>='0' && c<='9') res=(res<<1) + (res<<3) + c-'0',c=getchar();
return res*f;
}
inline ll Max(re ll x,re ll y){return x>y?x:y;}
inline ll Min(re ll x,re ll y){return x<y?x:y;}
inline void cmax(re auto &x,re auto y){x=Max(x,y);}
inline void cmin(re auto &x,re auto y){x=Min(x,y);}
/*-----------------*/
const int N=1e5+10;
int n,k;
struct P{
string t;int len;
bool friend operator <(P a,P b){
for(re int i=0;i<a.len&&i<b.len;i++){
if(a.t[i]<b.t[i]) return true;
if(a.t[i]>b.t[i]) return false;
}
return a.len<b.len;
}
inline void print(){
for(re int i=0;i<len;i++) putchar(t[i]);
}
}a[N],A,B;
inline bool check(re int x,re int y){
int lx=a[x].len,ly=a[y].len;
if(lx>ly) swap(lx,ly),swap(x,y);
for(re int i=0;i<lx;i++)
if(a[x].t[i]!=a[y].t[i]) return 1;
return 0;
}
int nxt[N][2];
inline void solve(re int x){
int p=1;
for(re int i=2;i<=x;i++){
int lx=a[p].len,ly=a[i].len;A=B={"",lx*ly};
for(re int j=1;j<=ly;j++) A.t=A.t+a[p].t;
for(re int j=1;j<=lx;j++) B.t=B.t+a[i].t;
if(B<A){
nxt[i][0]=p;
for(re int j=0;j<ly-lx+1;j+=lx){
bool F=0;
for(re int u=0;u<lx;u++)
if(a[i].t[j+u]!=a[p].t[u]){
F=1;break;
}
if(F) break;
nxt[i][1]++;
}
p=i;
}
}
while(k){
while(k<=nxt[p][1]) p=nxt[p][0];
a[p].print();k--;
}
}
int main(){
n=read();k=read();
for(re int i=1;i<=n;i++){
string s;cin>>s;
a[i]={s,s.size()};
}
sort(a+1,a+n+1);
for(re int i=1;i<n;i++)
if(check(i,i+1)) return solve(i),0;
return solve(n),0;
}
::::