bzoj 4698: Sdoi2008 Sandy的卡片 (后缀数组+二分)
来源:互联网 发布:小公司网络组建 编辑:程序博客网 时间:2024/05/20 11:49
题目描述
传送门
题解
二分答案,判断是否有一段区间的height都大于当前答案,并且包含n个串中的每个串。
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define N 2000003using namespace std;int xx[N],yy[N],v[N],sa[N],rank[N],height[N],a[N];int n,m,tp,len,ti,p,vis[N],belong[N],*x,*y;int cmp(int i,int j,int l){ return y[i]==y[j]&&(i+l>len?-1:y[i+l])==(j+l>len?-1:y[j+l]);}void get_sa(){ m=tp; p=0; x=xx; y=yy; for (int i=1;i<=len;i++) v[x[i]=a[i]]++; for (int i=1;i<=m;i++) v[i]+=v[i-1]; for (int i=len;i>=1;i--) sa[v[x[i]]--]=i; for (int k=1;k<=len;k<<=1) { p=0; for (int i=len-k+1;i<=len;i++) y[++p]=i; for (int i=1;i<=len;i++) if (sa[i]>k) y[++p]=sa[i]-k; for (int i=1;i<=m;i++) v[i]=0; for (int i=1;i<=len;i++) v[x[y[i]]]++; for (int i=1;i<=m;i++) v[i]+=v[i-1]; for (int i=len;i>=1;i--) sa[v[x[y[i]]]--]=y[i]; swap(x,y); x[sa[1]]=1; p=2; for (int i=2;i<=len;i++) x[sa[i]]=cmp(sa[i],sa[i-1],k)?p-1:p++; if (p>len) break; m=p+1; } for (int i=1;i<=len;i++) rank[sa[i]]=i; p=0; for (int i=1;i<=len;i++) { if (rank[i]==1) continue; int j=sa[rank[i]-1]; while (i+p<=len&&j+p<=len&&a[i+p]==a[j+p]) p++; height[rank[i]]=p; p=max(0,p-1); }}bool check(int k){ ti++; int cnt=0; for (int i=1;i<=len;i++) if (height[i]>=k) { if (vis[belong[sa[i]]]!=ti&&belong[sa[i]]) cnt++; vis[belong[sa[i]]]=ti; if (cnt==n) return true; } else { cnt=1; ti++; vis[belong[sa[i]]]=ti; if (!belong[sa[i]]) cnt=0; } return false;}int main(){ freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d",&n); tp=4021; len=0; int mx=0; for (int i=1;i<=n;i++) { int k,last; scanf("%d",&k); mx=max(mx,k); scanf("%d",&last); for (int j=2;j<=k;j++){ int x; scanf("%d",&x); ++len; belong[len]=i; a[len]=x-last+2000; last=x; } a[++len]=++tp; } get_sa(); int l=0; int r=mx; int ans=0; while (l<=r) { int mid=(l+r)/2; if (check(mid)) ans=max(ans,mid),l=mid+1; else r=mid-1; } printf("%d\n",ans+1);}
0 0
- bzoj 4698: Sdoi2008 Sandy的卡片 (后缀数组+二分)
- bzoj4698 [Sdoi2008] Sandy的卡片(后缀数组+二分答案)
- bzoj 4698 Sandy的卡片 后缀数组
- BZOJ 4698 Sdoi2008 Sandy的卡片
- BZOJ 4698: Sdoi2008 Sandy的卡片
- bzoj4698Sdoi2008 Sandy的卡片 后缀数组+二分
- [BZOJ4698][Sdoi2008]Sandy的卡片(后缀数组+st表||后缀自动机)
- 后缀自动机 【Sdoi2008】 Sandy的卡片 bzoj4698
- BZOJ4698 Sdoi2008 Sandy的卡片
- Bzoj4698: [Sdoi2008]Sandy的卡片
- bzoj4698 Sdoi2008 Sandy的卡片
- [bzoj4698][SDOI2008]Sandy的卡片
- 【SDOI2008】Sandy的卡片 DP
- NKOJ 2522 Sandy的卡片(差分数组+DP)
- Sandy 的卡片 card
- bzoj 3230: 相似子串 (后缀数组+RMQ+二分)
- bzoj 4310: 跳蚤 (后缀数组+二分+ST表)
- poj1743(后缀数组+二分)
- jupyter安装与卸载
- Spring Boot(2)—— 构建Hello World
- 去除BOM头问题
- 二十六 Swift3.0之 方法
- UVa 1588 Kickdown
- bzoj 4698: Sdoi2008 Sandy的卡片 (后缀数组+二分)
- ImageLoadAsyncTask--MainActivity
- emmc 通过reset controller 来reset emmc host
- 说说显示器接口那点事!VGA、DVI、HDMI,DP
- 【LeetCode】 237. Delete Node in a Linked List C语言
- LeetCode笔记:386. Lexicographical Numbers
- CentOS 7 安装GitLab
- Linux下打补丁
- Java程序员必须掌握的8大排序算法