sicily 1023. Funny Contest

很久之前做了,但是弄了好久才弄懂,现在看一下后缀数组又懵了。。。我弱爆了。。

题目就是按照后缀数组的倍增算法,因为倍增算法用倍增算法排序后,刚好可以统计这次得到的名次。

不过原始的后缀数组不是一个循环的字符串,我们把它改成循环就行了

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值