题目描述给你一个字符串,对字符串每个排序过的前缀排序,找到第k大的
例子
输入:adcba 3
分析:
排序过的前缀
a
ad
acd
abcd
aabcd
对排序过的前缀排序
a
aabcd
abcd
acd
ad
输出 abcd
#include <functional>
#include <iostream>
#include <string>
using namespace std;
struct node{
int pos;
int pre=0,next=0;
node(int _pos,int _pre,int _next):pos(_pos),pre(_pre),next(_next){};
};
vector<int> c(200,0);
vector<node> lis;
string s,ans;
int head=0,tail=0;
int addNext(int id,int pos){
if(id==tail){
lis[id].next=tail=lis.size();
lis.push_back(node(pos,id,tail));
}else{
int n=lis[id].next;
lis[n].pre=lis[id].next=lis.size();
lis.push_back({pos,id,n});
}
return (lis.size()-1);
}
int addPre(int id,int pos){
int p=lis[id].pre;
lis[p].next=lis[id].pre=lis.size();
lis.push_back(node(pos,p,id));
return (lis.size()-1);
}
stack<char> t;
int main(){// bacdacdbac
int T,n,k;cin>>T;
s.reserve(100000);
lis.reserve(100000);
ans.reserve(100000);
lis.push_back(node(-1,0,0));
while(T--){
lis.resize(1,node(-1,0,0));tail=0;
cin>>s>>k;n=s.size();
char mx=s[0];
c[mx]=addNext(tail,0);
t.push(mx);
for(int i=1;i<n;i++){
while(!t.empty()&&s[i]<t.top()) t.pop();
if(t.empty()&&s[i]<mx) c[mx]=addNext(tail,i);
else if(t.empty()&&s[i]>=mx) c[s[i]]=addPre(c[mx],i),t.push(s[i]);
else{
c[s[i]]=addPre(c[t.top()],i);
if(s[i]>t.top())t.push(s[i]);
}
mx=max(mx,s[i]);
}
ans.clear();
while(--k) tail=lis[tail].pre;
int num=lis[tail].pos+1;
for(char i='a';i<='z';i++) c[i]=0;
for(int i=0;i<num;i++) c[s[i]]++;
for(char i='a';i<='z';i++) while(c[i]--) ans.push_back(i);
cout<<ans<<endl;
}
}