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的更多相关文章

  1. UVALive - 6856 Circle of digits 后缀数组+二分

    题目链接: http://acm.hust.edu.cn/vjudge/problem/82135 Circle of digits Time Limit: 3000MS 题意 把循环串分割成k块,让 ...

  2. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

  3. Gym - 102028H Can You Solve the Harder Problem? (后缀数组+RMQ+单调栈)

    题意:求一个序列中本质不同的连续子序列的最大值之和. 由于要求“本质不同”,所以后缀数组就派上用场了,可以从小到大枚举每个后缀,对于每个sa[i],从sa[i]+ht[i]开始枚举(ht[0]=0), ...

  4. [whu1564]后缀数组

    http://acm.whu.edu.cn/land/problem/detail?problem_id=1564 思路:先把串复制一遍,在末尾补个标记,后缀数组跑一下,扫一遍就ok了(过滤后缀在后半 ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  6. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  7. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  8. 2016多校联合训练4 F - Substring 后缀数组

    Description ?? is practicing his program skill, and now he is given a string, he has to calculate th ...

  9. (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 ...

随机推荐

  1. java知识大全积累篇

    原文出自:http://www.importnew.com/14429.html 构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使 ...

  2. [原]OpenGL基础教程(五)缓冲区数据更新方式

    1.glBufferSubData 适用于相同数据类型 void SetPositionY(float y){    vector<Vector3<float>>::itera ...

  3. exerunexplorer.exe

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  4. windbg常用命令

    SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols CPU常用命令 载入sos.dll  执行.load C:\Windows\Micr ...

  5. volley二次封装

    产品中使用Volley框架已有多时,本身已有良好封装的Volley确实给程序开发带来了很多便利与快捷.但随着产品功能的不断增加,服务器接口的不断复杂化,直接使用Volley原生的JSONObjectR ...

  6. CodeWarrior环境下中断使用

    对于飞思卡尔CodeWarrior的中断使用,一般有3种方法: 1.把#pragma TRAP_PROC放在中断程序前面,并把中断向量表放到*.prm. 例如: #pragma TRAP_PROC v ...

  7. Unity数据存储路径总结

    一.在项目根目录中创建Resources文件夹来保存文件.可以使用Resources.Load("文件名字,注:不包括文件后缀名");把文件夹中的对象加载出来.注:此方可实现对文件 ...

  8. Microsoft 2013 新技术学习笔记 四

    在继续学习Model的实践经验之前,先思考一下Controller和View的实践原则在本次系统重构中的应用,我手上是一个后台管理系统(不是门户系统.不是具体业务系统),通俗点讲就是给企业的运维人员用 ...

  9. shell来start、stop、restart应用程序模板

    这里使用shell中的case语法: case分支语句格式如下: case $变量名 in 模式1) 命令列表 ;; 模式2) 命令列表 ;; *) ;; esac case行尾必须为单词“in”,每 ...

  10. [转载]在Vmware ESXI中安装群晖Synology DSM 5.0 (4528)

    转载 在Vmware ESXI中安装群晖Synology DSM 5.0 (4528) 文件准备 Vmware ESXi用户安装需要的文件 NB_x64_5032_DSM_50-4528_Xpenol ...