后缀数组 --- WOj 1564 Problem 1564 - A - Circle
Problem 1564 - A - Circle
Problem's Link: http://acm.whu.edu.cn/land/problem/detail?problem_id=1564
Mean:
给你一个长度不超过1e6的数字串,求第k大的环状数字串的前面那个位置。
analyse:
好吧,我承认这是个水题,比赛的时候sb了,因为原来做过后缀自动机求解字符串的环状最小表示法,所以一直用后缀自动机的知识去套k小表示法,比赛的时候太固执了。
这题就是后缀数组的sa[]数组的运用,sa[i]=k表示的是字符串所有的后缀按字典序排序后,第i个后缀排在第k个。
那么我们只需将数字串复制一遍接在原串后面(环状),对s求一遍后缀数字得到sa数组,然后找到sa<=n的第k个sa,那么sa[i]-1就是答案。
为什么?看这张图:

连接后的字符串我们可以得到2*n个字符串,但是我们只需关心前n个字符串就可,因为后面的n个字符串其实根本没作用,他们只相当于前n个字符串的前缀的重复出现而已。
所以我们只需要找到满足sa[i]<=n的第k个就行,sa[i]-1就是答案。
Time complexity: O(n)
Source code:
// Memory Time
// 1347K 0MS
// by : crazyacking
// 2015-04-20-19.00
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#define MAXN 1000010
#define LL long long
using namespace std;
const int maxn = ;
int Rank[maxn],wb[maxn],wv[maxn],wss[maxn]; bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
} void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x=Rank,*y=wb,*t;
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[x[i]=r[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--)
sa[--wss[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p)
{
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[wv[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return;
} char s[maxn];
int r[maxn],sa[maxn];
int main()
{
int n,k;
while(~scanf("%d %d",&n,&k))
{
getchar();
gets(s);
int len = strlen(s),i;
for(int i=len;i<len*;++i) s[i]=s[i-len];
s[len*]='\0';
len=len*;
for(int i=;i<len;++i)
s[i]+='a'-'';
len++;
for(i=; i<len-; i++)
r[i] = s[i]-'a'+;
r[len-] = ;
da(r,sa,len,);
int idx=;
for(int i=;i<len;++i)
{
if(sa[i]+<=n)
{
idx++;
if(idx==k) printf("%d\n",sa[i]!=?sa[i]:n);
}
}
}
return ;
}
#include<cstdio>
#include<vector>
#include<cstring>
#define MAXN 1000010
using namespace std;
int n,k,len,si,now;
char s[MAXN];
vector<int> num;
int GetAns(vector<int>tp,int tk,int l)
{
if(tp.size()== || l==n-) return tp[];
vector<int> cnt[];
si=tp.size();
for(int i=;i<si;++i)
cnt[s[ (tp[i]+l)%n ]-''].push_back(tp[i]);
now=;
while(tk>cnt[now].size())
{
tk-=cnt[now].size();now++;
}
return GetAns(cnt[now],tk,l+);
}
int main()
{
while(~scanf("%d %d",&n,&k))
{
scanf("%s",s);
len=strlen(s);
num.clear();
for(int i=;i<=len;++i) num.push_back(i);
printf("%d\n",GetAns(num,k,));
}
return ;
}
后缀数组 --- WOj 1564 Problem 1564 - A - Circle的更多相关文章
- UVALive - 6856 Circle of digits 后缀数组+二分
题目链接: http://acm.hust.edu.cn/vjudge/problem/82135 Circle of digits Time Limit: 3000MS 题意 把循环串分割成k块,让 ...
- HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...
- Gym - 102028H Can You Solve the Harder Problem? (后缀数组+RMQ+单调栈)
题意:求一个序列中本质不同的连续子序列的最大值之和. 由于要求“本质不同”,所以后缀数组就派上用场了,可以从小到大枚举每个后缀,对于每个sa[i],从sa[i]+ht[i]开始枚举(ht[0]=0), ...
- [whu1564]后缀数组
http://acm.whu.edu.cn/land/problem/detail?problem_id=1564 思路:先把串复制一遍,在末尾补个标记,后缀数组跑一下,扫一遍就ok了(过滤后缀在后半 ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- POJ1743 Musical Theme [后缀数组]
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 27539 Accepted: 9290 De ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- 2016多校联合训练4 F - Substring 后缀数组
Description ?? is practicing his program skill, and now he is given a string, he has to calculate th ...
- (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...
随机推荐
- Codeforces Round #384 (Div. 2) E. Vladik and cards 状压dp
E. Vladik and cards 题目链接 http://codeforces.com/contest/743/problem/E 题面 Vladik was bored on his way ...
- 关于VS2010出现“此方法显式使用的 CAS 策略已被 .NET Framework 弃用... ...请使用 NetFx40_LegacySecurityPolicy 配置开关”解决办法
有时候VS会出现“此方法显式使用的 CAS 策略已被 .NET Framework 弃用.若要出于兼容性原因而启用 CAS 策略,请使用 NetFx40_LegacySecurityPolicy 配置 ...
- 用户管理 之 Linux 用户管理工具介绍
Linux是一个多用户的操作系统,她有完美的用户管理工具,这些工具包括用户的查询.添加.修改,以及用户之间相互切换的工具等:通过这些工具,我们能安全.轻松的完成用户管理: 在这里我们要引入用户控制工具 ...
- 构造函数和:this()的应用
一.构造函数和:this()的应用 //本实例演示构造函数和:this()的应用 public class ClsA { public string A{set;get;} public string ...
- c语言二叉树
Department of Computing and Information SystemsCOMP10002 Foundations of AlgorithmsSemester 2, 2014As ...
- Mac OS 下安装rar unrar命令
环境 操作系统:Mac OS X 10.9.4 1. 下载 地址: http://www.rarlab.com/rar/rarosx-5.2.0.tar.gz 2. 安装 解压后进入目录 MacBoo ...
- Hadoop - Azkaban 作业调度
1.概述 在调度 Hadoop 的相关作业时,有以下几种方式: 基于 Linux 系统级别的 Crontab. Java 应用级别的 Quartz. 第三方的调度系统. 自行开发 Hadoop 应用调 ...
- winform C#获得Mac地址,IP地址,子网掩码,默认网关
1.添加程序集 2.引入命名空间 using System.Management; 3.方法 ManagementClass mc = new ManagementClass("Win32_ ...
- git删除远程文件夹或文件的方法
由于本地修改了文件夹大全名大小写的原因,同步到git上并不区分大小写,造成了一些文件同步不了,所以要先把git远程库上文件夹删除掉,然后再重新同步 如下,我把src里的全部移除,但是本地文件还保留. ...
- nohup启动java命令导致dubbo无法注册
没有任何异常,日志和正常注册日志一模一样,但服务就是没注册成功. 解决办法,screen代替nohup命令. screen screen -ls screen -r pid (ctrl + a)+d