很久之前做了,但是弄了好久才弄懂,现在看一下后缀数组又懵了。。。我弱爆了。。
题目就是按照后缀数组的倍增算法,因为倍增算法用倍增算法排序后,刚好可以统计这次得到的名次。
不过原始的后缀数组不是一个循环的字符串,我们把它改成循环就行了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 110000;
struct node{
int w;
int loca;
}data[maxn];
bool ccmp(node a,node b){
return a.w<b.w;
}
int r[maxn];
int sa[maxn];
int c[maxn];
int k[maxn];
int tt[maxn];
int n;
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[(a+l)%n]==r[(b+l)%n];}
int wa[maxn],wb[maxn],wv[maxn],wws[maxn];
void da(int *r,int *sa,int n,int m)
{
memset(c,0,sizeof(c));
///测试数据aabaaaab
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) wws[i]=0;
for(i=0;i<n;i++) wws[x[i]=r[i]]++;
for(i=1;i<m;i++) wws[i]+=wws[i-1];
for(i=n-1;i>=0;i--) sa[--wws[x[i]]]=i;
memset(tt,0,sizeof(tt));
tt[1] = 1;
for(p=1,k[sa[0]]=0,i=1;i<n;i++){
k[sa[i]]=r[sa[i-1]]==r[sa[i]]?p-1:p++;
tt[ k[ sa[i] ]+1 ]++;
}
//for(int i = 0;i<n;i++)cout <<k[i]<<" ";
//cout <<endl;
// for(i = 0;i<n;i++)cout <<k[i]<<" ";
//cout <<endl;
// cout <<tt[0]<<" ";
for(int i = 2;i<n;i++)tt[i] +=tt[i-1];
//cout <<endl;
for(i = 0;i<n;i++){
c[i]+=tt[k[i]];
/// cout <<c[i]<<" ";
}
///这里sa得到的是只按第一个关键字排序的结果。。
////sa[i]表示排第i的是原来的字符串"aabaaaab"的哪个位置
////如 此时 0 1 3 4 5 6 2 7
//for(i = 0;i<n;i++)printf("%d ",sa[i]);
//cout <<endl;
for(j=1,p=1;j*2<=n;j*=2,m=p)
{
////按第二个关键字进行排序
//// for(p=0,i=n-j;i<n;i++) y[p++]=i;/////长度不及2j的第二个,第二个关键字就是没有,那么全部应该排前
p = 0;
for(i=0;i<n;i++) y[p++]=(sa[i]-j+n)%n;
///此时sample 结果 y : 7 0 2 3 4 5 1 6
// for(int i = 0;i<n;i++)cout <<y[i]<<" ";
// cout <<endl;
//system("pause");
//x数组保存的是rank的结果
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) wws[i]=0;
for(i=0;i<n;i++) wws[wv[i]]++;
for(i=1;i<m;i++) wws[i]+=wws[i-1];
for(i=n-1;i>=0;i--) sa[--wws[wv[i]]]=y[i];
//for(int i = 0;i<n;i++)cout <<x[i]<<" ";
// cout <<endl;
memset(tt,0,sizeof(tt));
tt[1] = 1;
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++){
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
tt[x[sa[i]]+1]++;
// cout <<p<<endl;;
}
for(int i = 2;i<n;i++)tt[i] +=tt[i-1];
for(i = 0;i<n;i++)c[i]+=tt[x[i]];
/*for(int i = 0;i<n;i++)cout <<sa[i]<<" ";
cout <<endl;*/
// for(int i = 0;i<n;i++)cout <<x[i]<<" ";
// cout <<endl;
//system("pause");
}
printf("%d",c[0]);
for( i = 1;i<n;i++)printf(" %d",c[i]);
printf("\n");
return;
}
int main(){
while(scanf("%d",&n)!=EOF){
//int n;
//scanf("%d",&n);
for(int i = 0;i<n;i++){
scanf("%d",&data[i].w);
data[i].loca = i;
}
sort(data,data+n,ccmp);
int cou =1;
r[data[0].loca] = 1;
for(int i = 1;i<n;i++)if(data[i].w==data[i-1].w)r[data[i].loca] = cou;
else {
r[data[i].loca] = ++cou;
}
da(r,sa,n,n+1);
///int l = n;
//for(int i = 0;i<l;i++)printf("%d ",sa[i]);
}
return 0;
}
1023. Funny Contest