写一种\(O(nm)\)的做法,也就是\(O(\sum 串长)\)的。

先通过差分转化,把每个数变成这个数与上一个数的差,第一个数去掉,答案就是最长公共子串+1

按照套路把所有串拼起来,中间加一个分隔符号,然后用DC3求出SA以及height

(DC3我也不会,蒯的TJJ的板子,因为一般用倍增SA足够了)

对每个后缀可以知道它在原来的第几个串,那么求出SA以后,答案就是一段区间\([l,r]\),即排名为\([l,r]\)的这些后缀,而且必须覆盖原来的所有串,长度就是这些后缀的LCP,就是一段height的最小值

枚举左端点,那么最小的右端点一定不小于上一个的最小右端点,所以直接维护右端点以及这一段区间包括原来每一个串的数量就好了

最小值可以直接单调队列维护

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef unsigned long long ulint;
namespace input
{
const int bufl = 1<<14;
char buf[bufl],*s=buf,*t=buf;
inline int fetch()
{
if(s==t){t=(s=buf)+fread(buf,1,bufl,stdin);if(s==t)return EOF;}
return *s++;
}
inline int gi()
{
register int a=0,b=1,c=fetch();
while(!isdigit(c))b^=c=='-',c=fetch();
while(isdigit(c))a=a*10+c-48,c=fetch();
return b?a:-a;
}
}
using input::gi;
const int N = 202007 , N3 = N*3 , maxalpha = 99999;
int wa[N3],wb[N3],wv[N3],buc[N3];
inline void bsort(int *s,int *a,int *b,int n,int m)
{
register int i;
for(i=0;i<n;i++)wv[i]=s[a[i]];
for(i=0;i<m;i++)buc[i]=0;
for(i=0;i<n;i++)buc[wv[i]]++;
for(i=1;i<m;i++)buc[i]+=buc[i-1];
for(i=n-1;i>=0;i--)b[--buc[wv[i]]]=a[i];
}
inline int c0(int *s,int a,int b)
{
return s[a]==s[b] && s[a+1]==s[b+1] && s[a+2]==s[b+2];
}
inline int c12(int k,int *s,int a,int b)
{
if(k==2)return s[a]<s[b] || (s[a]==s[b] && c12(k-1,s,a+1,b+1));
return s[a]<s[b] || (s[a]==s[b] && wv[a+1]<wv[b+1]);
}
#define f(x) ((x)/3+((x)%3==1?0:tb))
#define g(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
void dc3(int *s,int *sa,int n,int m)
{
int i,j,*sn=s+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
s[n]=s[n+1]=0;
for(i=0;i<n;i++)if(i%3!=0)wa[tbc++]=i;
bsort(s+2,wa,wb,tbc,m),bsort(s+1,wb,wa,tbc,m),bsort(s,wa,wb,tbc,m);
for(sn[f(wb[0])]=0,p=1,i=1;i<tbc;i++)sn[f(wb[i])]=c0(s,wb[i-1],wb[i])?p-1:p++;
if(p<tbc)dc3(sn,san,tbc,p);
else for(i=0;i<tbc;i++)san[sn[i]]=i;
for(i=0;i<tbc;i++)if(san[i]<tb)wb[ta++]=san[i]*3;
if(n%3==1)wb[ta++]=n-1;
bsort(s,wb,wa,ta,m);
for(i=0;i<tbc;i++)wv[wb[i]=g(san[i])]=i;
for(i=j=p=0;i<ta && j<tbc;p++)sa[p]=c12(wb[j]%3,s,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++)sa[p]=wa[i++];
for(;j<tbc;p++)sa[p]=wb[j++];
}
#undef f
#undef g
void calheight(int *s,int *sa,int n,int *rk,int *ht)
{
register int i,j,k=0;
for(i=1;i<=n;++i)rk[sa[i]]=i;
for(i=0;i<n;ht[rk[i++]]=k)for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k] && k<n;++k);
return;
}
char s[N3];
int n,ss[N3],sa[N3],rk[N3],ht[N3];
int p[N3],S[N3];
int que[N3],hd,tl,cnt[N3];
int main()
{
int NN=gi(),n=0,sep=0;
if(NN==1)return printf("%d\n",gi()),0;
while(NN--){
int t=gi(),lst=gi();
while(--t){
int x=gi();
S[n++]=lst-x+10000;
lst=x;
}
S[n++]=++sep;
}
s[n]=0;
dc3(S,sa,n+1,20000);
calheight(S,sa,n,rk,ht);
int k=1;
for(int i=0;i<n;++i)if(S[i]>1000)p[i]=k;else ++k;//p[i]是后缀i属于原来的第几个串
int CNT=0,r=k,Mx=0;//cnt是原来每个串的出现次数,CNT是总的
hd=tl=0;
--k;
for(int i=k+1;i<=n;++i){
while(r<=n&&CNT<k){
if(cnt[p[sa[r]]]++==0)++CNT;
if(r){
while((hd^tl)&&ht[que[tl-1]]>ht[r])--tl;
que[tl++]=r;
}
++r;
}
if(CNT<k)break;
while((hd^tl)&&que[hd]<=i)++hd;
if(hd^tl)Mx=std::max(Mx,ht[que[hd]]);
if(--cnt[p[sa[i]]]==0)--CNT;
}
printf("%d\n",Mx+1);
return 0;
}

(大括号换行的是蒯的板子,不换行的也就是核心代码是我自己写的,DC3只是为了保证复杂度而已)

P2463 [SDOI2008]Sandy的卡片的更多相关文章

  1. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

    P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...

  2. bzoj4698 / P2463 [SDOI2008]Sandy的卡片

    P2463 [SDOI2008]Sandy的卡片 直接二分长度暴力匹配....... 跑的还挺快 (正解是后缀数组的样子) #include<iostream> #include<c ...

  3. P2463 [SDOI2008]Sandy的卡片[差分+串拼接后缀数组]

    P2463 [SDOI2008]Sandy的卡片 套路都差不多,都是差分后二分答案找lcp.只是这题要把多个串拼接起来成为一个大串,中间用某些值域中没有的数字相隔(最好间隔符都不一样想想为什么),排序 ...

  4. 洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)

    题目链接:https://www.luogu.org/problem/P2463 [题意] 求出N个串中都出现的相同子串的最长长度,相同子串的定义如题:所有元素加上一个数变成另一个,则这两个串相同,可 ...

  5. Luogu P2463 [SDOI2008]Sandy的卡片

    题目链接 \(Click\) \(Here\) 真的好麻烦啊..事实证明,理解是理解,一定要认认真真把板子打牢,不然调锅的时候真的会很痛苦..(最好是八分钟能无脑把\(SA\)码对的程度\(QAQ\) ...

  6. 洛咕 P2463 [SDOI2008]Sandy的卡片

    哈希水过. 首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段 由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力c ...

  7. [洛谷P2463][SDOI2008]Sandy的卡片

    题目大意:有$n$个字符串,求这$n$个字符串中最长的相似公共字串,相似的定义是加上一个数后相同 题解:差分,建广义后缀自动机,然后求出每个点在多少个字符串中出现过,若在$n$个中都出现,就更新答案 ...

  8. BZOJ 4698: Sdoi2008 Sandy的卡片

    4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 106  Solved: 40[Submit][Stat ...

  9. BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]

    4698: Sdoi2008 Sandy的卡片 题意:差分后就是多个串LCS SAM+map大法好 模板打错 智力-2 #include <iostream> #include <c ...

随机推荐

  1. Django CMDB

    cp:https://www.cnblogs.com/wupeiqi/articles/6192986.html https://www.cnblogs.com/sss4/p/10131953.htm ...

  2. 【转】python version 2.7 required,which was not found in the registry

    源地址:http://www.cnblogs.com/thinksasa/archive/2013/08/26/3283695.html 方法:新建一个register.py 文件,把一下代码贴进去, ...

  3. aix rootvg镜像

    就一般生产系统而已,操作系统层面都要进行备份,而最常见的操作系统备份方式之一就是做镜像(mirror),而实践过程中,往往是把rootvg这个卷组做镜像操作.查看rootvg是否已经进行镜像方法: 1 ...

  4. svn其它

    参考地址: http://www.cnblogs.com/mymelon/p/5483215.html

  5. wing ide 6.0 注册

    1.wing ide介绍 wing ide ,用过python的都知道是干嘛用的了吧,官网已经更新到6.0.0-1版本. 链接如下: Wing IDE Professional - Version 6 ...

  6. MySQL运维之---mysqldump备份、select...into outfile、mysql -e 等工具的使用

    1.mysqldump备份一个数据库 mysqldump命令备份一个数据库的基本语法: mysqldump -u user -p pwd dbname > Backup.sql 我们来讲解一下备 ...

  7. django模板系统(下)

    主要内容:母版,继承母版,块,组件,静态文件 母版 <!DOCTYPE html> <html lang="en"> <head> <me ...

  8. 1.1环境的准备(一)之Python解释器的安装

    目录: 1.Python-解释器的下载 2.Python-解释器的安装 3.Python-解释器的测试 4.Python的环境变量的配置 (一)Python解释器的安装: 1.官网:https://w ...

  9. 团队-UML

    UML设计 分工 刘双玉 李佳铭 杜宏庆 肖小强 汪志彬 江郑 符天愉 邓弘立 后台数据库 求购模块 浏览检索商品 即时聊天系统 商品管理 管理员系统 后台商品发布收藏系统 登录注册与个人信息系统 U ...

  10. 获取QQ头像接口

    https://q4.qlogo.cn/g?b=qq&nk=QQ号码&s=140