HDU 5431
由于最长不超过30个字符(由K的范围确定),于是,枚举所有的字符串,二分中使用二分就可以确定第K小了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; char str[20010]; int bits[32]; int save[32][20010]; int tmp[32]; int findindex(int i,int key){ int l=1,r=save[i][0]; int m,ans=0; while(l<=r){ int m=(l+r)/2; if(save[i][m]<=key){ ans=m; l=m+1; } else r=m-1; } return ans; } int main(){ int kase,now,T,K; scanf("%d",&kase); for(int i=1;i<32;i++) bits[i]=(1<<i); while(kase--){ scanf("%s",str); int len=strlen(str); for(int i=0;i<31;i++) save[i][0]=0; for(int i=0;i<len;i++){ now=0; for(int j=i;j<=min(i+29,len-1);j++){ now=(now<<1)+(str[j]-'A'); save[j-i+1][++save[j-i+1][0]]=now; } } for(int i=1;i<=30;i++) sort(save[i]+1,save[i]+save[i][0]+1); for(int i=1;i<=30;i++) { save[i][0]=unique(save[i]+1,save[i]+save[i][0]+1)-(save[i]+1); // cout<<save[i][0]<<endl; } // cout<<(char)(save[1][1]+'A')<<endl; scanf("%d",&T); int ans,ansbit; while(T--){ scanf("%d",&K); ans=-1; for(int i=1;i<=30;i++){ // cout<<K<<endl; if(K>bits[i]-save[i][0]){ K-=(bits[i]-save[i][0]); continue; } int l=0,r=bits[i]-1; while(l<=r){ int m=(l+r)>>1; int pos=findindex(i,m); // cout<<m<<" "<<pos<<endl; if(K>m+1-pos) l=m+1; else if(K<m+1-pos) r=m-1; else{ ans=m; while(ans==save[i][pos]&&pos!=0){ ans--; pos--; } break; } } // system("pause"); if(ans!=-1){ ansbit=i; break; } // else K-=(bits[i]-save[i][0]); } int cnt=0; // cout<<ans<<endl; while(ansbit--){ tmp[cnt++]=ans%2; ans/=2; } while(cnt--) printf("%c",tmp[cnt]+'A'); puts(""); } } return 0; }