BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)
求多串的最长公共字串.
法1: 二分长度+hash 传送门
法2: 二分+后缀数组 传送门
法3: 后缀自动机
拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再在全局取最小值(因为是所有串的公共串)就行了.
CODE
#include<bits/stdc++.h>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
	char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
	for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 2005;
const int C = 26;
int m, lk[MAXN<<1], ch[MAXN<<1][C], len[MAXN<<1], mx[MAXN<<1], mn[MAXN<<1], bin[MAXN<<1], seq[MAXN<<1], sz, last;
inline void init() {
    last = sz = 0; ++sz;
    lk[0] = -1; len[0] = 0;
}
inline void Copy(int A, int B) {
    lk[A] = lk[B];
    memcpy(ch[A], ch[B], sizeof ch[B]);
}
inline int insert(int p, int c) {
    int cur = sz++; last = cur;
    len[cur] = len[p] + 1;
    for(; ~p && !ch[p][c]; p = lk[p]) ch[p][c] = cur;
    if(p == -1) lk[cur] = 0;
    else {
        int q = ch[p][c];
        if(len[p] + 1 == len[q]) lk[cur] = q;
        else {
            int x = sz++;
            len[x] = len[p] + 1;
            Copy(x, q);
            lk[cur] = lk[q] = x;
            for(; ~p && ch[p][c] == q; p = lk[p]) ch[p][c] = x;
        }
    }
    return last;
}
inline void Match(char *s) {
    int p = 0, now = 0, j = 0;
    for(int c; s[j]; ++j) {
        if(ch[p][c=s[j]-'a'])
            ++now, p = ch[p][c];
        else {
            for(; ~p && !ch[p][c]; p = lk[p]);
            if(p == -1) now = p = 0;
            else now = len[p] + 1, p = ch[p][c];
        }
        mx[p] = max(mx[p], now);
    }
    for(int i = sz-1; i; --i) {
        mn[seq[i]] = min(mn[seq[i]], mx[seq[i]]);
        mx[lk[seq[i]]] = max(mx[lk[seq[i]]], mx[seq[i]]);
        mx[seq[i]] = 0;
    }
}
char s[MAXN];
int main() {
	read(m); scanf("%s", s);
	if(--m == 0) return printf("%d\n", strlen(s)), 0;
	init(); int p = 0;
	for(int i = 0; s[i]; ++i) p = insert(p, s[i]-'a');
    for(int i = 0; i < sz; ++i) ++bin[mn[i] = len[i]];
    for(int i = 1; i < sz; ++i) bin[i] += bin[i-1];
    for(int i = sz-1; ~i; --i) seq[--bin[len[i]]] = i;
	while(m--) scanf("%s", s), Match(s);
    int ans = 0;
	for(int i = 1; i < sz; ++i)
        ans = max(ans, mn[i]);
    printf("%d\n", ans);
}
BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)的更多相关文章
- BZOJ 2946: [Poi2000]公共串
		2946: [Poi2000]公共串 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 787 Solved: 342[Submit][Status][D ... 
- BZOJ 2946: [Poi2000]公共串( 后缀自动机 )
		一个串建后缀自动机, 其他串在上面跑, 然后用当前串跑的去更新全部 ------------------------------------------------------------------ ... 
- bzoj 2946: [Poi2000]公共串【SAM】
		对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会 ... 
- bzoj 2946 [Poi2000]公共串——后缀自动机
		题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946 对每个串都建一个后缀自动机,然后 dfs 其中一个自动机,记录同步的话在别的自动机上走 ... 
- BZOJ 2946 POI2000 公共串 后缀自动机(多串最长公共子串)
		题意概述:给出N个字符串,每个串的长度<=2000(雾...可能是当年的年代太久远机子太差了),问这N个字符串的最长公共子串长度为多少.(N<=5) 抛开数据结构,先想想朴素做法. 设计一 ... 
- BZOJ 2946 [Poi2000]公共串 ——后缀自动机
		任意选择一个串作为模式串,构建出后缀自动机. 然后用其他的串在后缀自动机上跑匹配. 然后就到了理解后缀自动机性质的时候. 在某一个节点的最大值是可以沿着parent树上传的. 然后用dp[i][j]表 ... 
- 【BZOJ 2946】 2946: [Poi2000]公共串 (SAM)
		2946: [Poi2000]公共串 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1063 Solved: 469 Description ... 
- 【BZOJ】2946: [Poi2000]公共串
		http://www.lydsy.com/JudgeOnline/problem.php?id=2946 题意:给n个串,求最大公共子串.(1<=n<=5,每个串长度<=2000) ... 
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
		BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ... 
随机推荐
- [转帖]Nginx 容器教程
			Nginx 容器教程 http://www.ruanyifeng.com/blog/2018/02/nginx-docker.html 里面有证书. 作者: 阮一峰 日期: 2018年2月27日 感谢 ... 
- c++练习—实现简单的4则运算
			#pragma once class Counter { public: void setExp(const char* exp);//设置表达式 void cleanExp(); //清除表达式 v ... 
- B2B、B2C、C2C、O2O分别是什么意思?
			1.B2B 是指进行电子商务交易的供需双方都是商家(或企业.公司),她(他)们使用了互联网的技术或各种商务网络平台,完成商务交易的过程.电子商务是现代 B2B marketing的一种具体主要的表现形 ... 
- Jmeter之压测探索和结果分析
			1.copy过来的,很有道理的一句话~ 最大并发数:取决于你的业务类型,数据量,处理时的资源需求等,具体多少,需要做一些性能测试来衡量 确定待测试的场景,设计脚本,不断增加并发数量. 2.CPU压不上 ... 
- java——多线程知识点大总结
			1:理解线程的概念之前,我们有必要先理解一下进程的概念 程序(Program)是为实现特定目标或解决特定问题而用计算机语言(比如Java语言)编写的命令序列的集合. 进程指一个程序的一次执行过程 ... 
- golang(8):channel读写 & goroutine 通信
			goroutine 1.进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位 B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独 ... 
- 你不知道的css各类布局(四)之响应式布局
			响应式布局 概念 响应式布局指的是同一页面在不同屏幕尺寸下有不同的布局 布局特点 响应式设计的目标是确保一个页面在所有终端上(各种尺寸的PC.手机.手表.冰箱的Web浏览器等等)都能显示出令人满意的效 ... 
- JS基础_嵌套的for循环
			<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ... 
- 基于JWT的token身份认证方案(转)
			https://www.cnblogs.com/xiangkejin/archive/2018/05/08/9011119.html 一.使用JSON Web Token的好处? 1.性能问题. JW ... 
- 数组通常在JS中使用
			数组通常在JS中使用,例如具有相同名称的多个输入.如果它们是动态生成的,则需要在提交时确定它们是否是数组.如果(文件).MyList.长度!=“未定义”)此用法不正确.正确的是如果(文件.MyList ... 
