zoukankan      html  css  js  c++  java
  • Infinite Fraction Path HDU 6223 2017沈阳区域赛G题题解

    题意:给你一个字符串s,找到满足条件(s[i]的下一个字符是s[(i*i+1)%n])的最大字典序的长度为n的串。

    思路:类似后缀数组,每次倍增来对以i开头的字符串排序,复杂度O(nlogn)。代码很多地方借鉴后缀数组。

    倍增:比如这次排序好了长度为m的串,那么想扩展为长度为2*m的串则需要用i的排名为第一关键字,i+m的排名为第二关键字进行排序,这种排序正好可以使用基数排序。

    下面是代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=155555;
     6 int n;
     7 int m;
     8 int tp[maxn],Rank[maxn],SA[maxn],tax[maxn];
     9 void Rsort()///SA为排名为i的元素所在的位置,tp为第二关键字,Rank作为第一关键字,Rank为i元素的排名。
    10 {
    11     for(int i=0; i<=m; i++)tax[i]=0;
    12     for(int i=1; i<=n; i++)tax[Rank[tp[i]]]++;
    13     for(int i=1; i<=m; i++)tax[i]+=tax[i-1];
    14     for(int i=n; i>=1; i--)SA[tax[Rank[tp[i]]]--]=tp[i];
    15 }
    16 char st[maxn];
    17 int go[maxn][2];
    18 int main()
    19 {
    20     int t;
    21     while(~scanf("%d",&t))
    22     {
    23         int c=1;
    24         while(t--)
    25         {
    26             scanf("%d",&n);
    27             scanf("%s",st+1);
    28             for(long long i=1; i<=n; i++)
    29                 go[i][0]=((i-1)*(i-1)+1)%n+1;///滚动数组,倍增查找i后面的第2^k的位置。
    30             m=11;
    31             for(int i=1; i<=n; i++)
    32                 tp[i]=i,Rank[i]=st[i]-'0';
    33             int p;
    34             for(int t=0; t<18&&(1<<t)<=n; t++)
    35             {
    36                 for(int i=0;i<=m;i++)tax[i]=0;
    37                 for(int i=1; i<=n; i++)tax[Rank[go[i][t&1]]]++;
    38                 for(int i=1;i<=m;i++)tax[i]+=tax[i-1];
    39                 for(int i=1;i<=n;i++)tp[tax[Rank[go[i][t&1]]]--]=i;
    40                 Rsort();
    41                 swap(tp,Rank);
    42                 Rank[SA[1]]=p=1;
    43                 for(int i=2; i<=n; i++)Rank[SA[i]]=(tp[SA[i]]==tp[SA[i-1]]&&tp[go[SA[i]][t&1]]==tp[go[SA[i-1]][t&1]])?p:++p;
    44                 if(Rank[SA[n]]!=Rank[SA[n-1]])break;///剪枝,如果已经能确定最大的了  直接break
    45                 m=p;
    46                 for(int i=1;i<=n;i++)
    47                     go[i][!(t&1)]=go[go[i][t&1]][t&1];///这里是倍增,go[i]代表i后面第2^t的元素的位置
    48             }
    49             printf("Case #%d: ",c++);
    50             long long loc=SA[n]-1;
    51             for(int i=0; i<n; i++,loc=(loc*loc+1)%n)
    52                 printf("%c",st[loc+1]);
    53             puts("");
    54         }
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    zoj 3195 Design the city LCA Tarjan
    hdu 2586 How far away ? 离线LCA
    洛谷 P3379 【模板】最近公共祖先(LCA)Tarjan离线
    codeforces #446 892A Greed 892B Wrath 892C Pride 891B Gluttony
    设计模式(16)---原型模式
    设计模式(15)---享元模式
    设计模式(14)---组合模式
    设计模式(13)---外观模式
    设计模式(12)---适配器模式
    设计模式(11)---代理模式
  • 原文地址:https://www.cnblogs.com/xseventh/p/7887067.html
Copyright © 2011-2022 走看看