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 }
原文地址:https://www.cnblogs.com/xseventh/p/7887067.html