后缀数组 hash求LCP BZOJ 4310: 跳蚤
后缀数组的题博客里没放进去过。。所以挖了一题写写 充实下博客 顺便留作板子。。
一个字符串S中 内容不同的子串 有 sigma{n-sa[i]+1-h[i]} (噢 这里的h[]就是大家熟知的height[])
所以l=1,r=上述sigma 二分 答案是字典序第几大的子串。
然后 求S中第k大的子串W : 因为h[i]是与i-1有关的 所以要从n downto 1,k-=n-sa[i]+1-h[i] 至 k再减就非正了
显然这样扫过来 子串字典序是递减的 因此可以得到第k大子串W
然后再贪心 n downto 1 若遇到比 W大的子串 就划分,验证 当前二分的这个第k大可不可行
判断 比W大还是小 用hash 二分求LCP即可
#include <bits/stdc++.h>
#define N 200005
#define LL long long
using namespace std;
const LL mo=;
int F[],a[N],rank[N],sa[N],h[N],g1[N],g2[N],next[N],n,m,ans,k,t,l,r,mid,x,y,z;
char S[N]; LL f[N],w[N];
int oh(int k,int t,int p,int q){
int l=,r=min(t-k,q-p)+,j;
while (l<r){
j=l+r+>>;
(f[k+j-]-f[k-]*w[j]%mo+mo)%mo==(f[p+j-]-f[p-]*w[j]%mo+mo)%mo?
l=j:r=j-;
}
if (k+l>t) return ;
if (p+l>q) return ;
return a[k+l]>a[p+l];
}
int jud(int u){
int p,q,k,t;
for (int i=n;i;--i)
if (n-sa[i]+-h[i]<u) u-=n-sa[i]+-h[i];
else {p=sa[i];q=n-u+;break;}
t=n; k=;
for (int i=n;i;)
if (oh(i,t,p,q)){
if (i==t) return ;
t=i; ++k;
} else --i;
if (k>m) return ; return ;
}
int main(){
scanf("%d",&m); scanf("%s",S+); n=strlen(S+);
w[]=;
for (int i=;i<=n;++i) {
a[i]=S[i]-'a'+;
F[a[i]]=;
f[i]=(f[i-]*+a[i])%mo;
w[i]=w[i-]*%mo;
}
for (int i=;i<=;++i) F[i]+=F[i-];
for (int i=;i<=n;++i) rank[i]=F[a[i]]; t=F[];
for (int m=;m<n;m<<=){
for (int i=;i<=n;++i){
next[i]=g1[rank[i+m]];
g1[rank[i+m]]=i;
}
for (int i=t;i>=;--i){
for (int j=g1[i];j;j=k){
k=next[j]; next[j]=g2[rank[j]]; g2[rank[j]]=j;
}
g1[i]=;
}
z=;
for (int i=;i<=t;++i){
y=-;
for (int j=g2[i];j;j=k){
k=next[j]; next[j]=;
if (y!=rank[j+m]) y=rank[j+m],++z;
h[j]=z;
}
g2[i]=;
}
t=z;
for (int i=;i<=n;++i) rank[i]=h[i];
}
for (int i=;i<=n;++i) sa[rank[i]]=i,h[i]=;
for (int i=,k=;i<=n;++i)
if (rank[i]!=){
if (k) --k;
while (a[i+k]==a[sa[rank[i]-]+k]) ++k;
h[rank[i]]=k; r+=n-i+-k;
}
l=; ++r;
while (l<r){
k=l+r+>>;
jud(k)?l=k:r=k-;
}
for (int i=n;i;--i)
if (n-sa[i]+-h[i]<l) l-=n-sa[i]+-h[i];
else {k=sa[i];t=n-l+;break;}
for (int i=k;i<=t;++i) printf("%c",a[i]+'a'-);
return ;
}
Assassin
后缀数组 hash求LCP BZOJ 4310: 跳蚤的更多相关文章
- bzoj 4310 跳蚤 二分答案+后缀数组/后缀树
题目大意 给定\(k\)和长度\(\le10^5\)的串S 把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串 ...
- bzoj 4310: 跳蚤
Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典 ...
- ●BZOJ 4310 跳蚤
●赘述题目 给出一个字符串,要求分成k个子串,然后求出每个子串的字典序最大的子串(我称它为子子串),要使这k个子子串中的字典序最大的那个串(即魔力串)最小.输出该魔力串. (本题个人感觉很好,比较综合 ...
- HDU-4622 Reincarnation 后缀数组 | Hash,维护和,扫描
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给一个字符串,询问某字串的不同字串的个数. 可以用后缀数组来解决,复杂度O(n).先求出倍 ...
- FJUT3703 这还是一道数论题(二分 + hash + manacher 或者 STL + hash 或者 后缀数组 + hash)题解
Problem Description 最后来个字符串签个到吧,这题其实并不难,所需的算法比较基础,甚至你们最近还上过课. 为了降低难度,免得所有人爆零.这里给几个提示的关键字 :字符串,回文,二分, ...
- URAL - 1297 后缀数组的做法 LCP应用
题意:求最长回文子串 这种有专门的O(n)套板子算法,但作为练习还是用后缀数组来解吧 只需把相同的另一个串反接(中间用一个足够小且未出现的字符衔接),然后枚举回文串的中点,不断求解该点往前和往后计算的 ...
- Uva12206 Stammering Aliens 后缀数组&&Hash
Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all effort ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- URAL 1297 后缀数组:求最长回文子串
思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. ...
随机推荐
- hdu 1500 dp
/* 状态转移方程式: dp[i][j]=Min(dp[i][j-1],dp[i-1][j-2]+(a[j-1]-a[j])*(a[j-1]-a[j])); 依次求出第i个人在第j个数时的所求的最小值 ...
- Couriers(bzoj 3524)
Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. ...
- CodeForces - 356A Knight Tournament
http://codeforces.com/problemset/problem/356/A 首先理解题意 每次给出l 和r 在l - r之间还有资格的选手中得出一个胜者 暴力思路: 首先维护还有资 ...
- OC-Xcode中导入runtime框架,函数参数没有提示的处理方法
在了解runtime时,如果自己编写runtime代码,需要先导入头文件: #import <objc/message.h> 之后,例如了解runtime的消息机制时,调用objc_msg ...
- Codeforces 954 D Fight Against Traffic
Discription Little town Nsk consists of n junctions connected by m bidirectional roads. Each road co ...
- mysql 统计数据,按照日期分组,把没有数据的日期也展示出来
因为业务需求,要统计每天的新增用户并且要用折线图的方式展示. 如果其中有一天没有新增用户的话,这一天就是空缺的,在绘制折线图的时候是不允许的,所有要求把没有数据的日期也要在图表显示. 查询2019-0 ...
- MAC上反编译android apk---apktool, dex2jar, jd-jui安装使用(含手动签名)
前文 介绍了在Windows平台利用强大的APK-Multi-Tool进行反编译apk,修改smali源码后再回编译成apk的流程,最近受人之托,破解个apk,所幸的是所用到的这三个软件都是跨平台的, ...
- CentOS 6.x Radius
CentOS 6.x Radius 一. 实现环境: 1.系统:CentOS release 6.6 (Final) 2.需要软件包: 1) freeradius-2.1.12-6.e16.x ...
- DosBox 报错 this program requires dosxnt.exe to be in your path
也就是少了dosxnt.exe文件,能够上网搜索下载,把dosxnt 拷贝到你挂截文件夹下就能够执行 Dosxnt文件下载
- MySQL 当记录不存在时插入,当记录存在时更新
第一种: 示例一:插入多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语句: INSERT INTO clients (client_id,client_name ...