\(\text{Suffix Tree:}\)我来啦我来啦

\(\text{Solution:}\)

题目要求求好几个串串的\(\text{LCS.}\)

由于串串的数量并不多,所以我们把它们塞到一个\(\text{Suffix Tree}\)里面,中间加上分隔符号。

那么答案就是最深的且它的子树中具有所有分节符的非叶子节点。

至于分节符数量和种类,用前缀和即可。

介于\(\text{Suffix Tree}\)压缩的性质,菜鸡笔者还不太清楚一边插入一边维护的方法,求指教。

前缀和维护的原理:由于最前面的绝对先出现,所以从第一个枚举到最后一个,看看这个区间中是不是有这个串串的分节符。如果有,跳出即可。因为它所代表的后缀只属于这一个串串。

至于如何判断这些分节符是不是都有,用了状压。\(\text{1<<i}\)表示第\(i\)个分节符有没有,统计的时候用或运算即可。

话说\(\text{Fread}\)可以读入这种非固定数量的字符咩?

#include<bits/stdc++.h>
#include<ctime>
using namespace std;
const int MAXN=2e6+10;
char Z[20][100001];
int n,val[MAXN],ans,M,tot,num;
int sum[20][MAXN];
const int inf=(1<<30);
struct SuffixTree {
int link[MAXN],ch[MAXN][50],now,rem,n;
int start[MAXN],len[MAXN],tail,s[MAXN];
SuffixTree() {
tail=now=1;
rem=n=0;
len[0]=inf;
}
inline int build(int a,int b) {
link[++tail]=1;
start[tail]=a;
len[tail]=b;
return tail;
}
void Extend(int x) {
s[++n]=x;
++rem;
for(int last=1; rem;) {
while(rem>len[ch[now][s[n-rem+1]]])
rem-=len[now=ch[now][s[n-rem+1]]];
int &v=ch[now][s[n-rem+1]];
int c=s[start[v]+rem-1];
if(!v||x==c) {
link[last]=now;
last=now;
if(!v)v=build(n,inf);
else break;
} else {
int u=build(start[v],rem-1);
ch[u][c]=v;
ch[u][x]=build(n,inf);
start[v]+=rem-1;
len[v]-=rem-1;
link[last]=v=u;
last=u;
}
if(now==1)--rem;
else now=link[now];
}
}
} T;
void predfs(int u,int dep) {
if(dep>=inf) {
int L=T.start[u];
int R=L+T.len[u]-1;
R=min(R,T.n);
for(int i=1;i<=num;++i){
if(sum[i][R]-sum[i][L-1]){
val[u]|=(1<<i);
break;
}
}
return;
}
for(int i=0; i<=25+num; ++i) {
if(T.ch[u][i]) {
predfs(T.ch[u][i],dep+T.len[T.ch[u][i]]);
val[u]|=val[T.ch[u][i]];
}
}
if(val[u]==M)ans=max(ans,dep);
}
int main() {
while(scanf("%s",Z[++num]+1)!=EOF);
num--;
int G='0';int len=strlen(Z[1]+1);
Z[1][++len]=(char)G;
for(int i=2;i<=num;++i){
G++;
int L=strlen(Z[i]+1);
for(int j=1;j<=L;++j)Z[1][++len]=Z[i][j];
Z[1][++len]=(char)G;
}
for(int i=1;i<=num;++i)M+=(1<<i);
for(int i=1;i<=len;++i){
if(Z[1][i]>='a')T.Extend(Z[1][i]-'a');
else T.Extend(Z[1][i]-'0'+1+25);
}
for(int i=1;i<=len;++i){ for(int j=1;j<=num;++j)sum[j][i]=sum[j][i-1];
if(T.s[i]>25){
int V=T.s[i]-25;
sum[V][i]++;
}
}
predfs(1,0);
cout<<ans<<endl;
return 0;
}

注意,分节符不要超过\(\text{ASCII}\)表的范围,不然喜提\(RE.\)

【题解】SP1812 【LCS2 - Longest Common Substring II 】的更多相关文章

  1. SP1812 LCS2 - Longest Common Substring II

    能匹配上子串的节点对它的所有parent都有贡献 在树上转移即可 #include<cstdio> #include<algorithm> #include<cstrin ...

  2. 【SP1812】LCS2 - Longest Common Substring II

    [SP1812]LCS2 - Longest Common Substring II 题面 洛谷 题解 你首先得会做这题. 然后就其实就很简单了, 你在每一个状态\(i\)打一个标记\(f[i]\)表 ...

  3. SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS

    LCS2 - Longest Common Substring II no tags  A string is finite sequence of characters over a non-emp ...

  4. SPOJ LCS2 - Longest Common Substring II

    LCS2 - Longest Common Substring II A string is finite sequence of characters over a non-empty finite ...

  5. spoj1812 LCS2 - Longest Common Substring II

    地址:http://www.spoj.com/problems/LCS2/ 题面: LCS2 - Longest Common Substring II no tags  A string is fi ...

  6. spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)

    spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 < ...

  7. SPOJ1812 LCS2 - Longest Common Substring II【SAM LCS】

    LCS2 - Longest Common Substring II 多个字符串找最长公共子串 以其中一个串建\(SAM\),然后用其他串一个个去匹配,每次的匹配方式和两个串找\(LCS\)一样,就是 ...

  8. 题解 SP1812 【LCS2 - Longest Common Substring II 】

    对于本题这样的多字符串的子串匹配问题,其实用广义后缀自动机就可以很好的解决,感觉会比普通的后缀自动机做法方便一些. 首先记录出每个节点被多少个字符串更新,也就是记录每个节点有多少个字符串能到达它,可以 ...

  9. LCS2 - Longest Common Substring II(spoj1812)(sam(后缀自动机)+多串LCS)

    A string is finite sequence of characters over a non-empty finite set \(\sum\). In this problem, \(\ ...

  10. 【刷题】SPOJ 1812 LCS2 - Longest Common Substring II

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

随机推荐

  1. 【pytest】teardown里的yield和addfinalizer

    在之前介绍pytest中的fixture用法的文章中https://zhuanlan.zhihu.com/p/87775743,提到了teardown的实现. 最近在翻pytest官方文档的时候,又发 ...

  2. [HGAME Week2] Cosmos的博客后台

    觉得这道题考察的东西比较综合而且比较简单,就写上了.因为写这篇文章的时候环境已经关闭了,所以引用了其他师傅wp的图片 本题考察了:php://filter伪协议文件包含.var_dump()输出GLO ...

  3. directives 自定义指令

    钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选): bind:只调用一次,指令第一次绑定到元素时调用.在这里可以进行一次性的初始化设置.基本数据类型如果发生改变,不会触发,但是引用数据 ...

  4. 【CF】Sereja and Arcs

    #include <bits/stdc++.h> #define llong long long using namespace std; const int N = 1e5; const ...

  5. 索引对单列极值查询的显著性影响(百万级别表单列最值查询 Cost由1405变成3)

    表结构: create table hy_emp( id number(7,0) primary key, name nvarchar2(20) not null, salary number(5,0 ...

  6. nginx安装第三方模块echo

    要使用第三方模块ngx_echo的功能,请重新配置添加到nginx插件中 ##下载第三方模块 wget https://github.com/openresty/echo-nginx-module/a ...

  7. 创建node节点上kubeconfig文件

    #!/bin/bash#by love19791126 107420988@qq.com# 创建node节点上kubeconfig文件 在master节点部署#kubeconfig是用于Node节点上 ...

  8. SpringBoot打Jar包在命令行运行

    首先写一个测试文件 然后点击IDEA右侧的maven,然后选择package,之后点击上面运行或者直接双击即可, 等下方控制台构建成功即可: 然后找到项目目录下target下即可看到打的jar包 然后 ...

  9. webstorm中emmet展开a标签和行内元素不换行的解决办法

    大家好我是木瓜太香,大家在使用 webstorm 编写 html 的时候可能会遇到展开部分标签挨在一起的情况,相信很多小伙伴都想解决这个问题,接下来我们就开始吧! 先来看看我们输入如下 emmet 代 ...

  10. CTF-WeChall-第一天

    2020.09.09 今天来了一个新平台,WeChall,从简单的开始做,才能找到自信--i春秋的题做自闭了