\(\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.\)

最新文章

  1. spring ioc
  2. Swift中类与结构的初始化
  3. 基于SignalR的web端即时通讯 - ChatJS
  4. 如果下次做模板,我就使用Nvelocity
  5. Linux 性能监控、测试、优化工具
  6. Part 86 to 88 Talking about Multithreading in C#
  7. hadoop错误org.apache.hadoop.yarn.exceptions.YarnException Unauthorized request to start container
  8. J2EE 关于WebLogic下应用使用URL.openConnection获取连接返回 HttpsURLConnection与SOAPHttpsURLConnection的问题
  9. WebStorm 的使用(一)
  10. MVC数据提交
  11. arm:c语言和汇编混合编程
  12. A - 小彭玉的扫荡食堂计划
  13. Adobe Photoshop CS6中文破解MAC版
  14. 新安装mysql 第三方工具连接不上问题
  15. Java Socket 服务端发送数据 客户端接收数据
  16. 编译原理---antlr实践+编译过程理解+课程理解知识点
  17. dubbo系列二:dubbo常用功能总结
  18. emacs org-mode文件转html文件
  19. goreplay,tcpcopy
  20. 图解Fiddler如何抓取Android数据包

热门文章

  1. Istio 的配置分析
  2. 阿里云体验实验室 体验教程《Linux指令入门-系统管理》
  3. ASP.NET Core 进程内与进程外的性能对比
  4. Avtiviti工作流规范 BPM与BPMN
  5. java之5分钟插入千万条数据
  6. 使用HttpUrlConnection访问www.163.com遇到503问题,用设置代理加以解决
  7. 关于Vue的那些事儿
  8. C#编辑GridView的Thead
  9. python中的n次方表示法 **n
  10. [LeetCode]面试题 01.06. 字符串压缩