bzoj4698Sdoi2008 Sandy的卡片 后缀数组+二分
来源:互联网 发布:java系统日工具 编辑:程序博客网 时间:2024/05/20 13:40
其实不是很难的一道题,但是被坑了很久= =。。。
首先他没有给出字符集所以我们要自己算出来。
然后,离散一下,这里的离散是把所有的数字变成他们之间的差(这个很显然但是不好想,可能是我有点sb想了半天才想到)
然后SA求出height以后二分判断的时候扫一遍看看连续LCP>=mid的是否有n个就可以了。
#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define inf 2000000000using namespace std;const int N=3e5+5;int n;int vis[1005];int b[N],c[N],d[N],height[N],sa[N],rank[N];int s[N];int mx=0,mn=inf,L=1,R=inf;int tot,l[N],r[N],a[1005][1005],id[N];inline void getsa(int n,int m){ fo(i,0,m)b[i]=0; fo(i,1,n)b[s[i]]++; fo(i,1,m)b[i]+=b[i-1]; fd(i,n,1)c[b[s[i]]--]=i; int t=0; fo(i,1,n) { if (s[c[i]]!=s[c[i-1]])t++; rank[c[i]]=t; } int j=1; while (j<=n) { fo(i,0,n)b[i]=0; fo(i,1,n)b[rank[i+j]]++; fo(i,1,n)b[i]+=b[i-1]; fd(i,n,1)c[b[rank[i+j]]--]=i; fo(i,0,n)b[i]=0; fo(i,1,n)b[rank[i]]++; fo(i,1,n)b[i]+=b[i-1]; fd(i,n,1)d[b[rank[c[i]]]--]=c[i]; int t=0; fo(i,1,n) { if (rank[d[i]]!=rank[d[i-1]]|| rank[d[i]]==rank[d[i-1]]&&rank[d[i]+j]!=rank[d[i-1]+j])t++; c[d[i]]=t; } fo(i,1,n)rank[i]=c[i]; if (t==n)break; j*=2; } fo(i,1,n)sa[rank[i]]=i;}inline void getheight(){ int k=0; fo(i,1,tot) { if (k) k--; int j=sa[rank[i]-1]; while (i+k<=tot&&j+k<=tot&&s[i+k]==s[j+k]) k++; height[rank[i]]=k; }}inline bool pd(int x){ int num=0; fo(i,1,tot) { if (height[i]<x) { num=0; memset(vis,0,sizeof(vis)); } if (!vis[id[sa[i]]]) { vis[id[sa[i]]]=1; num++; } if (num==n)return 1; } return 0;}int main(){ scanf("%d",&n); fo(i,1,n) { scanf("%d",&l[i]); fo(j,1,l[i]) { scanf("%d",&a[i][j]); if (j!=1)mx=max(mx,a[i][j]-a[i][j-1]); } R=min(R,l[i]); } fo(i,1,n) { fo(j,2,l[i]) { s[++tot]=a[i][j]-a[i][j-1]; id[tot]=i; } s[++tot]=++mx; } fo(i,1,tot)mn=min(s[i],mn); fo(i,1,tot) { s[i]=s[i]-mn+1; mx=max(mx,s[i]); } getsa(tot,mx); getheight(); //printf("%d %d %d\n",mx,mn,tot); int ans=1; while (L<=R) { int mid=(L+R)>>1; if (pd(mid)) { ans=mid+1,L=mid+1; } else R=mid-1; } printf("%d\n",ans);}
阅读全文
0 0
- bzoj4698Sdoi2008 Sandy的卡片 后缀数组+二分
- bzoj 4698: Sdoi2008 Sandy的卡片 (后缀数组+二分)
- bzoj4698 [Sdoi2008] Sandy的卡片(后缀数组+二分答案)
- bzoj 4698 Sandy的卡片 后缀数组
- 后缀自动机 【Sdoi2008】 Sandy的卡片 bzoj4698
- [BZOJ4698][Sdoi2008]Sandy的卡片(后缀数组+st表||后缀自动机)
- Sandy 的卡片 card
- NKOJ 2522 Sandy的卡片(差分数组+DP)
- BZOJ4698 Sdoi2008 Sandy的卡片
- Bzoj4698: [Sdoi2008]Sandy的卡片
- bzoj4698 Sdoi2008 Sandy的卡片
- [bzoj4698][SDOI2008]Sandy的卡片
- 【SDOI2008】Sandy的卡片 DP
- BZOJ 4698 Sdoi2008 Sandy的卡片
- BZOJ 4698: Sdoi2008 Sandy的卡片
- 洛谷P2463 SDOI【2008】 sandy的卡片 kmp
- poj3294 二分+后缀数组
- poj1743(后缀数组+二分)
- 别忙着改BUG了_先干了这碗鸡汤!
- 6种方法实现asp.net返回上一页
- [Unity&C#]浅谈接口interface 的意义
- node.js配置到sae初探
- ~/.vimrc
- bzoj4698Sdoi2008 Sandy的卡片 后缀数组+二分
- *arg的用法
- 第五章——数组和广义表
- 云服务器LNMP环境搭建
- 计算广告学习笔记2.2 合约广告系统-合约广告简介
- linux应用项目(一)数码相框(2)数码相框之freetype实现矢量字体的显示
- centos 7 安装redis
- 沈阳集训day7
- 源码分析之Android通过Dialer实现暗码启动