zoukankan      html  css  js  c++  java
  • hdu6223(后缀数组)

    题意:

      给一个长度为n的字符串s[0..n-1],但i的后继不再是i+1,而是(i*i+1)%n,求所有长度为n的“子串”中,字典序最大的是谁

      n<=150000

    分析:

      如果是一般的字符串,那么直接求出后缀数组就行,但现在后继关系发生了变化

      我们在倍增求后缀数组的过程中,只关心某个位置的下个2^k的后继,于是可以先倍增预处理出每个位置的nx[i][j]表示位置i的下个2^j的后继是谁

      时间复杂度O(nlogn)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2e5;
     4 char s[maxn+50];
     5 int sa[maxn+50],rk[maxn+50];
     6 int t[maxn+50],t2[maxn+50],c[maxn+50];
     7 int nx[maxn+5][19];
     8 int len,k;
     9 queue<int> q[maxn+5];
    10 void getsa(int m)//m表示最大字符的编码
    11 {
    12     memset(t,-1,sizeof(t));
    13     memset(t2,-1,sizeof(t2));
    14     int *x=t,*y=t2;
    15     for(int i=0;i<m;++i) c[i]=0;
    16     for(int i=0;i<len;++i) c[x[i]=s[i]]++;
    17     for(int i=1;i<m;++i) c[i]+=c[i-1];
    18     for(int i=len-1;i>=0;--i) sa[--c[x[i]]]=i;
    19     for(int j=0,k=1;k<=len;k<<=1,++j)
    20     {
    21         /*int p=0;
    22         for(int i=len-k;i<len;++i) y[p++]=i;
    23         for(int i=0;i<len;++i) if(sa[i]>=k) y[p++]=sa[i]-k;*/
    24 
    25         int p=0;
    26         for(int i=0;i<len;++i) q[nx[i][j]].push(i);
    27         for(int i=0;i<len;++i)
    28             while(!q[sa[i]].empty())
    29             {
    30                 y[p++]=q[sa[i]].front();
    31                 q[sa[i]].pop();
    32             }
    33 
    34         for(int i=0;i<m;++i) c[i]=0;
    35         for(int i=0;i<len;++i) c[x[y[i]]]++;
    36         for(int i=0;i<m;++i) c[i]+=c[i-1];
    37         for(int i=len-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
    38         swap(x,y);
    39         p=1,x[sa[0]]=0;
    40         for(int i=1;i<len;++i)
    41             if(y[sa[i-1]]==y[sa[i]]&&y[nx[sa[i-1]][j]]==y[nx[sa[i]][j]]) x[sa[i]]=p-1;else x[sa[i]]=p++;
    42         if(p>=len) break;
    43         m=p;
    44     }
    45 }
    46 int main()
    47 {
    48     int T;
    49     scanf("%d",&T);
    50     for(int cas=1;cas<=T;++cas)
    51     {
    52         printf("Case #%d: ",cas);
    53         scanf("%d",&len);
    54         scanf("%s",s);
    55         for(int i=0;i<len;++i) nx[i][0]=(1LL*i*i+1)%len;
    56         for(int j=1;j<=18;++j)
    57             for(int i=0;i<len;++i) nx[i][j]=nx[nx[i][j-1]][j-1];
    58         getsa('9'+1);
    59         int pos=sa[len-1];
    60         for(int i=1;i<=len;++i,pos=nx[pos][0]) printf("%c",s[pos]);
    61         printf("
    ");
    62     }
    63 
    64    // for(int i=0;i<n;++i) printf("%d ",sa[i]);printf("
    ");
    65    // for(int i=0;i<n;++i) printf("%d ",rk[i]);printf("
    ");
    66    // for(int i=0;i<n;++i) printf("%d ",height[i]);printf("
    ");
    67     return 0;
    68 
    69 }
    View Code
  • 相关阅读:
    Max Sum Plus Plus HDU
    Monkey and Banana HDU
    Ignatius and the Princess IV HDU
    Extended Traffic LightOJ
    Tram POJ
    Common Subsequence HDU
    最大连续子序列 HDU
    Max Sum HDU
    畅通工程再续
    River Hopscotch POJ
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8993911.html
Copyright © 2011-2022 走看看