二分+后缀数组

先差分,然后找n个串的最长公共子串。
听说直接KMP O(n2m)O(n^2m) 可过,然而用后缀数组可以优化到 O(nmlogn)O(nmlogn)

做法是把所有串接起来,相邻两串之间用不同大数隔开,做SA。显然如果长度k能有公共子串,那么≤k肯定也可以。于是二分k,把所有连续的heigh值≥k的一段拎出来,看这一段是否包含了1~n的一些子串。有的话意味着存在这样的n个子串,否则不存在。

好久没摸SA,已经不会打了。对SA中的一句有一些疑问(见下面代码注释?处),为什么大家都是按照注释掉的代码打的呢。。。下一行那种不可以吗。。。[害怕.jpg]

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1005
#define cmax(u,v) (u)<(v)?(u)=(v):0
#define cmin(u,v) (u)>(v)?(u)=(v):0
using namespace std;
namespace runzhe2000
{int in(){int r = 0; char c = getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar();return r;}const int INF = 1<<29;int tot, len[N], pre[N][N], s[N*N], belong[N*N], sa[N*N], rank[N*N], t1[N*N], t2[N*N], sum[N*N], arr[N*N], height[N*N], ct[N];void SA(){int *x = t1, *y = t2, m = N*N-1;for(int i = 1; i <= tot; i++) sum[x[i] = s[i]]++;for(int i = 1; i <= m; i++) sum[i] += sum[i-1];for(int i = tot; i; i--) sa[sum[x[i]]--] = i;for(int k = 1, p = 0; k <= tot; k <<= 1, m = p, p = 0){for(int i = tot-k+1; i <= tot; i++) y[++p] = i;for(int i = 1; i <= tot; i++) if(sa[i] > k) y[++p] = sa[i] - k;for(int i = 1; i <= m; i++) sum[i] = 0;//          for(int i = 1; i <= tot; i++) sum[x[y[i]]]++; // ?for(int i = 1; i <= tot; i++) sum[x[i]]++; // ?for(int i = 1; i <= m; i++) sum[i] += sum[i-1];for(int i = tot; i; i--) sa[sum[x[y[i]]]--] = y[i];swap(x, y); x[sa[1]] = p = 1;for(int i = 2; i <= tot; i++) x[sa[i]] = y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k] ? p : ++p;}for(int i = 1; i <= tot; i++) rank[sa[i]] = i;for(int i = 1, j, k = 0; i <= tot; height[rank[i++]] = k)for(k ? k -- : 0, j = sa[rank[i]-1]; s[i+k] == s[j+k]; ++k); }bool check(int n, int lim){int timer = 0, cnt = 0;memset(ct,0,sizeof(ct));for(int i = 1; i <= tot; i++){if(height[i] < lim) ++timer, cnt = 0;int pos = belong[sa[i]];if(ct[pos] != timer && pos)ct[pos] = timer, ++cnt;if(cnt == n)return true;}return false;}void main(){int n = in(), mx = 0, mi_len = INF;for(int i = 1; i <= n; i++){len[i] = in(); cmin(mi_len, len[i]);for(int j = 1; j <= len[i]; j++)pre[i][j] = in(), cmax(mx, pre[i][j]);}for(int i = 1; i <= n; i++){for(int j = 2; j <= len[i]; j++)s[++tot] = pre[i][j] - pre[i][j-1], belong[tot] = i;s[++tot] = ++mx;} for(int i = 1; i <= tot; i++) arr[i] = s[i];sort(arr+1,arr+1+tot);int arr_cnt = unique(arr+1,arr+1+tot) - arr;for(int i = 1; i <= tot; i++) s[i] = lower_bound(arr+1,arr+1+arr_cnt,s[i]) - arr;SA();int l = 1, r = mi_len;while(l < r){int mid = (l+r+1)>>1;if(check(n, mid)) l = mid;else r = mid - 1;}printf("%d\n",l + 1);}
}
int main()
{runzhe2000::main();
} 

BZOJ 4698 Sdoi2008 Sandy的卡片相关推荐

  1. 4698: Sdoi2008 Sandy的卡片

    前言 总之这个东西说起来很麻烦就是了, 思路 差分合并+后缀数组+二分(dddl) 类似于那个bzoj1031的复制子串和那个poj1743的差分 来看个例子 3 5 1 2 3 4 5 4 1 1 ...

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

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

  3. 【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组

    题目描述 Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记,第i张卡片的序列 ...

  4. [SDOI2008]Sandy的卡片

    题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...

  5. BZOJ4698: Sdoi2008 Sandy的卡片

    题解: 裸后缀数组+二分答案 /**************************************************************Problem: 4698User: c20 ...

  6. [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)

    差分之后就是求多串LCS. 对其中一个串建SAM,然后把其它串放在上面跑. 对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值.答案就是res[ ...

  7. Luogu P2463 [SDOI2008]Sandy的卡片

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

  8. [luoguP2463] [SDOI2008]Sandy的卡片(后缀数组 + st表)

    传送门 很容易想到,题目中的相同是指差分数组相同. 那么可以把差分数组连起来,中间加上一个没有出现过的且字典序小的数 双指针移动,用st表维护height数组中的最小值. 当然用单调队列应该也可以且更 ...

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

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

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

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

最新文章

  1. pycharm禁用pytest
  2. 物体检测 迁移学习、IOU、NMS理解
  3. 2003年以来网页尺寸增长3倍
  4. 强烈推荐!孩子的科普从这套全球畅销250万册的最酷科学书起步
  5. c标签foreach遍历list_遍历 Dictionary,你会几种方式?
  6. 全国计算机等级考试用报名吗,全国计算机等级考试网上报名流程及考生报名使用说明...
  7. (王道408考研操作系统)第二章进程管理-第三节1:进程同步与互斥的基本概念
  8. Redis五大数据类型String、Hash、List、Set、ZSet
  9. form表单回车提交问题,JS监听回车事件
  10. nlp基础—12.LSTM-CRF模型介绍
  11. redies常用命令
  12. 5G牌照发放了,但需要购买5G手机的用户应等明年再购买
  13. 向量 数量积vs向量积
  14. CSDN日报20170224——《程序员该用哪种姿势来理财》
  15. win7怎样更改桌面计算机图标,教您电脑如何更改桌面图标
  16. C语言怎样提取一个数的十位个位百位千位
  17. #一日一图#中秋快乐之美工也放假
  18. php购物车页面如何做,HTML代码实现简易购物车
  19. mysql存储过程基础写法
  20. 高恪智能流控怎么设置_磊科285G智能QoS与高恪K2P智能流控多用户对比评测(下, 多用户对比测试)...

热门文章

  1. 中国身份证号码验证,支持15 18位,可验证成功90 的身份证号
  2. [云原生专题-1]:总体-云原生初步探究,什么是云原生,云原生的基本特性
  3. 响应式布局的基本介绍及原理
  4. 阿里在线笔试算法工程师附加题
  5. 机器学习数据集划分留出法,留一法,交叉法,自助法
  6. 北林信息学院计算机导师名单,北京林业大学信息学院计算机应用技术导师介绍:刘文萍...
  7. 人生得意须尽善,人生失意亦无怨;人生一世,草木一秋,乐也,悲也,何乐而不为呢?...
  8. pvt检查是什么意思_EVT、DVT、PVT是什么意思
  9. echarts散点图使用(转:http://www.suchso.com/UIweb/echarts-sandiantu.html)
  10. NIKE ZOOM ASTORIA SKY HI ACG (MUSTARD/TAN)