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
  • 相关阅读:
    WPF的本质:数据和行为
    WPF 布局
    wpf中的样式与模板
    WPF命令
    WPF数据转换
    WPF 深入研究 之 Control 控件
    WPF布局控件
    WPF TextBox 验证输入
    Razor引擎学习:RenderBody,RenderPage和RenderSection
    WPF控件模版
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8993911.html
Copyright © 2011-2022 走看看