【[SDOI2008]Sandy的卡片】
被\(mhr\)的暴力干翻了
这道题做法还是非常好想的
先做一遍差分,在每个串的某尾插入一个特殊字符,再将所有的串拼接在一起
现在的问题就转化为找到一个最长的公共子串使得其出现了\(n\)次,但是在一个串内出现多次出现只算一次
先考虑一下没有第二个限制的做法
那就是最简单的\(SA\)+二分了,就是扫一遍\(height\)数组,之后根据\(height\)进行分组使得一个组内所有的\(height\)都大于等于当前二分出来的\(mid\),之后一个组内有多少个就代表这个子串出现了多少次
现在有了限制,就是不能来自于同一个串
于是我们给每一个\(sa_i\)打一个标记,标记好其来自哪一个数组,之后对于一个组内出现的同一个串内的我们只需要算一次就够了
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define maxn (1000*100+1000+5)*2
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define pt putchar(1)
inline int read()
{
char c=getchar();int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int a[maxn],f[maxn],c[maxn];
int tp[maxn],sa[maxn],rk[maxn],tax[maxn],het[maxn],b[maxn];
int n,m,K,r,t;
inline void qsort()
{
for(re int i=0;i<=K;i++) tax[i]=0;
for(re int i=1;i<=n;i++) tax[rk[i]]++;
for(re int i=1;i<=K;i++) tax[i]+=tax[i-1];
for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
}
inline int check(int x)
{
int num=0,now=1;
if(f[sa[1]]) num++,b[f[sa[1]]]++;
for(re int i=2;i<=n;i++)
{
if(het[i]<x)
{
if(num>=m) return 1;
for(re int j=now;j<i;j++) b[f[sa[j]]]=0;
num=0,now=i;
if(f[sa[i]]) num++,b[f[sa[i]]]++;
continue;
}
if(!b[f[sa[i]]]&&f[sa[i]]) b[f[sa[i]]]++,num++;
}
return num>=m;
}
int main()
{
m=read();
for(re int i=1;i<=m;i++)
{
t=read();r=max(t,r);
for(re int j=1;j<=t;j++) a[++n]=read(),f[n]=i;
a[++n]=i+101,f[n]=0;
}
for(re int i=1;i<=n;i++) c[i]=a[i]-a[i-1];
for(re int i=1;i<=n;i++) c[i]+=2001,K=max(c[i],K);
c[1]=0;
for(re int i=1;i<=n;i++) tp[i]=i,rk[i]=c[i];
qsort();
for(re int w=1,p=0;p<n;K=p,w<<=1)
{
p=0;
for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
qsort();
for(re int i=1;i<=n;i++) std::swap(rk[i],tp[i]);
rk[sa[1]]=p=1;
for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
}
int k=0;
for(re int i=1;i<=n;i++)
{
if(k) --k;
int j=sa[rk[i]-1];
while(c[i+k]==c[j+k]) ++k;
het[rk[i]]=k;
}
int l=1,ans=0;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
printf("%d\n",ans+1);
return 0;
}
【[SDOI2008]Sandy的卡片】的更多相关文章
- BZOJ 4698: Sdoi2008 Sandy的卡片
4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 106 Solved: 40[Submit][Stat ...
- BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]
4698: Sdoi2008 Sandy的卡片 题意:差分后就是多个串LCS SAM+map大法好 模板打错 智力-2 #include <iostream> #include <c ...
- 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告
P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...
- bzoj4698 / P2463 [SDOI2008]Sandy的卡片
P2463 [SDOI2008]Sandy的卡片 直接二分长度暴力匹配....... 跑的还挺快 (正解是后缀数组的样子) #include<iostream> #include<c ...
- 【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ
[BZOJ4698]Sdoi2008 Sandy的卡片 Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡 ...
- 【BZOJ4698】[SDOI2008]Sandy的卡片
[BZOJ4698][SDOI2008]Sandy的卡片 题面 flag倒了. bzoj 洛谷 题解 首先题目的区间加很丑对吧, 将每个串差分一下,就可以转化为 求: 给定\(N\)个串,求他们的最长 ...
- P2463 [SDOI2008]Sandy的卡片[差分+串拼接后缀数组]
P2463 [SDOI2008]Sandy的卡片 套路都差不多,都是差分后二分答案找lcp.只是这题要把多个串拼接起来成为一个大串,中间用某些值域中没有的数字相隔(最好间隔符都不一样想想为什么),排序 ...
- [bzoj4698][Sdoi2008]Sandy的卡片_后缀数组_二分/单调队列_双指针
Sandy的卡片 bzoj-4698 Sdoi-2008 题目大意:题目链接. 注释:略. 想法: 这个题跟一个Usaco的题特别像.我们把这些串差分 现在我们要求的就是公共子串且出现次数不少于$k$ ...
- [SDOI2008]Sandy的卡片
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...
- 4698. [SDOI2008]Sandy的卡片【后缀数组】
Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积 攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记, ...
随机推荐
- sql server数据库导出表里所有数据
主要步骤: 连接数据库>选择需要导出数据的数据库>任务>生成脚本 点击下一步,选择特定数据库对象>选择需要导出的数据表,下一步 选择高级>要编写脚本的数据的类型:仅限数据 ...
- MongoDB基本用法(增删改高级查询、mapreduce)
TestCase.java package com.wujintao.mongo; import java.net.UnknownHostException; import java.util.Arr ...
- 第8天:javascriptDOM小 案例、onmouseover 、onmouseout
案例 为元素注册点击事件,弹出对话框 <input type="button" id="btn" value="开发分离"> & ...
- [javaEE] 控制浏览器缓存资源
浏览器有默认的缓存机制,不同的浏览器,缓存头是不一样的 设置编码,调用setContentType()方法,参数:”text/html;charset=utf-8” 关闭缓存,调用setHeader( ...
- 安装vmware player
一.简介 什么是虚拟机? 虚拟机是通过软件来模拟一个完整的计算机系统.简单来说,你可以在当前系统中通过虚拟机软件运行另外一个系统,并且与当前系统隔离. 什么是vmware? vmware(virtua ...
- 自定义经纬度索引(非RTree、Morton Code[z order curve]、Geohash的方式)
自定义经纬度索引(非RTree.Morton Code[z order curve].Geohash的方式) Custom Indexing for Latitude-Longitude Data 网 ...
- Java求一个数组中的最大值和最小值
原创作品,转载请注明出处:https://www.cnblogs.com/sunshine5683/p/9927186.html 今天在工作中遇到对一个已知的一维数组取出其最大值和最小值,分别用于参与 ...
- docker启动容器报错:IPv4 forwarding is disabled. Networking will not work
报这个错误会导致宿主机以外的pc 访问不了容器 按照网上的解决办法: 在/usr/lib/sysctl.d/00-system.conf文件后加net.ipv4.ip_forward=1 即可 然后重 ...
- The pit of an if statement in Java
package the.pit.of.an.ifstatement.injava; public class ThePitOfAnIfStatementInJava { public static v ...
- python装饰器 高阶函数 函数闭包
1.装饰器: 本质是函数,功能是为其他函数添加附加功能 原则:1.不修改被装饰函数的源代码 2.不修改被修饰函数的调用方式 装饰器=高阶函数+函数嵌套+闭包 #装饰器格式框架def wrap(func ...