【HDOJ6223】Infinite Fraction Path(后缀数组)

题意:

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

n<=150000,s[i]=0..9

思路:后缀数组

因为前驱与后继的关系已经变化,就不能用下标直接加减

i的后继是唯一的,i的前驱却不一定

所以对于后继使用倍增,对于前驱每个位置暴力开队列存储,需要的时候再拿出来

在判断的地方稍作修改

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<map>
  8 #include<set>
  9 #include<queue>
 10 #include<vector>
 11 #include<bits/stdc++.h>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef unsigned int uint;
 15 typedef unsigned long long ull;
 16 typedef pair<int,int> PII;
 17 typedef vector<int> VI;
 18 #define fi first
 19 #define se second
 20 #define MP make_pair
 21 #define N   310000
 22 #define MOD 1000000007
 23 #define eps 1e-8
 24 #define pi acos(-1)
 25 queue<int> q[N];
 26
 27 char ch[N];
 28 int n,s[N],sa[N],wa[N],wb[N],wc[N],wd[N],height[N],Rank[N],
 29     f[N][19];
 30
 31
 32 int read()
 33 {
 34    int v=0,f=1;
 35    char c=getchar();
 36    while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();}
 37    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 38    return v*f;
 39 }
 40
 41 bool cmp(int *r,int a,int b,int l)
 42 {
 43     return r[a]==r[b]&&r[f[a][l]]==r[f[b][l]];
 44 //    return r[a]==r[b]&&r[a+l]==r[b+l]; 原来的写法
 45 }
 46
 47 void getsa(int *r,int *sa,int n,int m)
 48 {
 49 //    printf("\n");
 50     int *x=wa,*y=wb,p;
 51     int k=0;
 52     for(int i=0;i<n;i++) wc[x[i]=r[i]]++;
 53     for(int i=1;i<m;i++) wc[i]+=wc[i-1];
 54     for(int i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
 55     for(int j=1,p=1;p<n;j*=2,m=p)
 56     {
 57         p=0;
 58         /*for(i=n-j;i<n;i++) y[p++]=i;
 59         for(i=0;i<n;i++)
 60          if(sa[i]>=j) y[p++]=sa[i]-j;
 61         */ //默认后继为i+1应该是这个写法
 62
 63         for(int i=0;i<n;i++) q[f[i][k]].push(i);
 64         for(int i=0;i<n;i++)
 65          while(!q[sa[i]].empty())
 66          {
 67              y[p++]=q[sa[i]].front();
 68              q[sa[i]].pop();
 69          }
 70         for(int i=0;i<n;i++) wd[i]=x[y[i]];
 71         for(int i=0;i<m;i++) wc[i]=0;
 72         for(int i=0;i<n;i++) wc[wd[i]]++;
 73         for(int i=1;i<m;i++) wc[i]+=wc[i-1];
 74         for(int i=n-1;i>=0;i--) sa[--wc[wd[i]]]=y[i];
 75         swap(x,y);
 76         p=1; x[sa[0]]=0;
 77         for(int i=1;i<n;i++)
 78          x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;
 79         //printf("%d %d %d\n",k,j,p);
 80         k++;
 81         if(j>n) break; //加上这句就A了,应该都是N很大,D[i]相同的数据吧,名次的并列很多
 82     }
 83 }
 84
 85
 86
 87 int main()
 88 {
 89     freopen("hdoj6223.in","r",stdin);
 90     freopen("hdoj6223.out","w",stdout);
 91     int cas;
 92     scanf("%d",&cas);
 93     for(int v=1;v<=cas;v++)
 94     {
 95         printf("Case #%d: ",v);
 96         scanf("%d",&n);
 97          scanf("%s",ch);
 98          for(int i=0;i<n;i++) s[i]=ch[i]-‘0‘+1;
 99          for(int i=0;i<n;i++) f[i][0]=(1LL*i*i+1)%n;
100
101         for(int j=1;j<=18;j++)
102          for(int i=0;i<n;i++) f[i][j]=f[f[i][j-1]][j-1];
103
104
105
106          s[n]=0;
107          getsa(s,sa,n+1,20);
108         int k=sa[n];
109         for(int i=1;i<=n;i++)
110         {
111             printf("%c",ch[k]);
112             k=f[k][0];
113         }
114         printf("\n");
115         for(int i=0;i<=max(20,n);i++)
116         {
117                s[i]=sa[i]=wa[i]=wb[i]=wc[i]=wd[i]=
118               Rank[i]=0;
119         }
120     }
121     return 0;
122 }
123      

原文地址:https://www.cnblogs.com/myx12345/p/9735730.html

时间: 2024-08-01 01:12:28

【HDOJ6223】Infinite Fraction Path(后缀数组)的相关文章

hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

题目传送门 题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会得到一个长度为n的数列,输出能得到的最大的数列(当成数字). 思路: 一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs. 但是bfs肯定要剪枝,怎么剪枝呢? 1.按照思路,我要取每一位尽可能大的值,所以某一个状态的某

HDU 6223 Infinite Fraction Path(BFS+剪枝)

The ant Welly now dedicates himself to urban infrastructure. He came to the kingdom of numbers and solicited an audience with the king. He recounted how he had built a happy path in the kingdom of happiness. The king affirmed Welly's talent and hoped

HDU6223——2017ICPC徐州G Infinite Fraction Path

题意: 给定一个数字串,每个位子都能向(i*i+1)%n的位子转移,输出路径上,字典序最大的,长度为n的串. 参考:https://www.cnblogs.com/mountaink/p/9541442.html 思路: BFS, 一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs. 但是bfs肯定要剪枝,怎么剪枝呢? 1.按照思路,我要取每一位尽可能大的值,所以某一个状态的某一位小于我当前以及有的解,这个状态肯定

ACM-ICPC 2017 沈阳赛区现场赛 G. Infinite Fraction Path &amp;&amp; HDU 6223

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6223 参考题解:https://blog.csdn.net/qq_40482495/article/details/78492841 注意优先队列自定义比较级的用法!! 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define

hdu 6223 Infinite Fraction Path

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6223 题意:给定长度为n的一串数字S,现在要按照一种规则寻找长度为n的数字串,使得该数字串的字典序最大.规则:从数字串S的某一个下标为x的数字出发,可以到达的下一个数字是下标为(x*x+1)%n的数字. 思路:BFS+剪枝.剪枝技巧: 1:遍历到某一层的节点时,记录已经到达过的节点,下次如果还经过就直接不考虑. 2:当前遍历到的某一层节点的数字较之前的小,直接不考虑. AC代码: #define _

HDU6223 &amp;&amp; 2017沈阳ICPC: G. Infinite Fraction Path——特殊图&amp;&amp;暴力

题意 给定一个数字串,每个位子都能向(i*i+1)%n的位子转移,输出在路径上.字典序最大的.长度为n的串($n \leq 150000$). 分析 先考虑一个暴力的方法,考虑暴力每个x,然后O(n)判定形成的字符串字典序是否比当前的最优解要大,复杂度O(n²),显然大家都会做. 而本题中有个结论:没有必要每次O(n),只要前100个字符一样,那么后面的一定都一样!所以>500直接break,复杂度O(500n), 可以过! 理解:对于所有的下标k,k向(k*k+1)%n连一条有向边,最后可以得

bnuoj 34990(后缀数组 或 hash+二分)

后缀数组倍增算法超时,听说用3DC可以勉强过,不愿写了,直接用hash+二分求出log(n)的时间查询两个字符串之间的任意两个位置的最长前缀. 我自己在想hash的时候一直在考虑hash成数值时MOD取多大,如果取10^18的话,那么两数相乘个就超LL了,但是取10^9的话又怕出现重复的可能大.后面才发现自己是sb,如果用unsigned long long 如果有溢出或者为负数是直接变成对(1<<64)取模了. 也就是无符号长整形运算自动帮你取模了.所以可以放心用hash Justice S

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

hdu5769--Substring(后缀数组)

题意:求含有某个字母的某个字符串的不同子串的个数 题解:后缀数组,记录每个位置距离需要出现的字母的距离就可以了.因为不太了解后缀模版卡了一会,还是很简单的. 记住sa和height数组都是1-n的下标. //后缀数组 #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll;