whu15校赛A题

Description
Here is a circle sequence S of length n, and you can choose a position and remove the number on it.
After that,you will get a integer. More formally,you choose a number x( 1<=x<=n ),then you will get the integer Rx = Sx+1……SnS1S2….. Sx-1.
The problem is which number x you choose will get the k-th smallest Rx.
If there are more than one answer,choose the one with the smallest x.
Input
First line of each case contains two numbers n and k.(2 ≤ k≤  n ≤ 1 000 000).

Next line contains a number of length n. Each position corresponds to a number of 1-9.
Output
Output x on a single line for each case.
Sample Input
10 5
6228814462
10 4
9282777691
Sample Output
6
7
 
比赛的时候并不会这个题,因为不会后缀数组,后来看题解才学了一下后缀数组。除了利用后缀数组预处理外本题还有个要点就是要把这个字符串复制成两份首位相接,直接处理就可以得到题目要求的环状的结果,最后计数的时候忽略起点在n/2以后的后缀即可,还有一点是本题要删除一个字符,所以删除字符的位置要判断一下
const int maxv=1e6+20;
int n,m;
int k;
int sa[maxv],rank[maxv],lcp[maxv],tmp[maxv];
string s;
bool cmp_sa(int a,int b){
	if(rank[a]!=rank[b])
		return rank[a]<rank[b];
	int ra=a+k<n?rank[a+k]:-1;
	int rb=b+k<n?rank[b+k]:-1;
	return ra<rb;
}
void cons_sa(){
	for(int i=0;i<=n;i++){ 
		rank[i]=i<n?s[i]:-1;
		sa[i]=i;
	}
	k=1;
	while(k<=n){
		sort(sa,sa+n+1,cmp_sa);
		tmp[sa[0]]=0;
		for(int i=1;i<=n;i++){
			tmp[sa[i]]=tmp[sa[i-1]]+(cmp_sa(sa[i-1],sa[i])?1:0);
		}
		for(int i=0;i<=n;i++) rank[i]=tmp[i];
		k<<=1;
	}
	
}
int main(){
	while(cin>>n>>m){
		cin>>s;
		s=s+s;
		n<<=1;
		cons_sa();
		int cont=0;
		int i=0;
		for(;;i++){
			if(sa[i]<n/2) m--;
			if(m==0){
				if(sa[i]==0){
					cout<<n/2<<endl;
				}
				else
					cout<<sa[i]<<endl;
				break;
			}
		}
	}
    return 0;
}

 

posted @ 2015-04-22 15:25  PlusSeven  阅读(187)  评论(0编辑  收藏  举报