题目链接:https://vjudge.net/problem/SPOJ-HACKING
解题思路:
建个后缀自动机,然后在树上跑前K个字符的dfs,直到遇到树上没有的即停止.
算法复杂度O(n*m)
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int mx = 2e4+10;
int n,m,K,cnt;
char str[mx],ans[mx];
struct sam{
int ch[mx][26];
int f[mx];
int len[mx];
int c[mx];
int id[mx];
int sz,rt,last;
int newnode(int v){
len[++sz] = v;
memset(ch[sz],0,sizeof(ch[sz]));
return sz;
}
void init(){
sz = 0;
rt = last = newnode(0);
}
void insert(int c){
int p = last,np = newnode(len[last]+1);
while(p&&!ch[p][c]) ch[p][c] = np,p = f[p];
if(!p) f[np] = rt;
else{
int q = ch[p][c];
if(len[q]==len[p]+1) f[np] = q;
else{
int nq = newnode(len[p]+1);
memcpy(ch[nq],ch[q],sizeof(ch[q]));
f[nq] = f[q];
f[q] = f[np] = nq;
while(p&&ch[p][c]==q) ch[p][c] = nq,p = f[p];
}
}
last = np;
}
bool dfs(int p){
if(cnt==m) return 0;
for(int i=K;~i;i--){
if(!ch[p][i]){
ans[cnt++] = i+'a';
return 1;
}
ans[cnt++] = i+'a';
if(dfs(ch[p][i])) return 1;
cnt--;
}
return 0;
}
}word;
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d%d",&n,&m,&K);
K--,cnt = 0;
scanf("%s",str);
word.init();
for(int i=0;i<n;i++) word.insert(str[i]-'a');
word.dfs(word.rt);ans[cnt] = 0;
puts(ans);
}
return 0;
}