Biology 题解
Biology 题解
题意简述
初始有\(n\)个字符串,有\(m\)个操作,操作分为两种:
- 插入一个新的字符串,下标递增(\(n+1,n+2,n+3\dots\))。
- 查询\(k\)个字符串\(x_1,x_2,\dots,x_k\)的最长公共后缀长度。
\(N\le50000,M\le100000,2\le T\le10,|S_i|\le10000,\sum|S_i|\le1000000,总字符串数量\le100000\)。

Solution
的确是百年难得一见的水题。
先将字符串反转,变成一个最长公共前缀问题。
暴力是肯定不行的,这个显然要\(\log\)才过得去。
所以使用\(trie\)维护前缀,\(LCA\)查询最长公共前缀。
最长公共前缀的深度就是公共前缀的长度。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std;
template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,m;
string reverse(string str)
{
for(int i=0;i<str.size()/2;i++)
{
swap(str[i],str[str.size()-i-1]);
}
// cout<<str<<endl;
return str;
}
struct Trie
{
int ch[1000010][26];
int cnt;
int v[100010];//将字符串编号映射到其末尾的节点
int dep[1000010],f[1000010][17];
Trie()
{
cnt=1;
memset(ch,0,sizeof(ch));
memset(v,0,sizeof(v));
}
void insert(string str,int pos)
{
int u=1;
for(int i=0;i<str.size();i++)
{
if(!ch[u][str[i]-'a']) ch[u][str[i]-'a']=++cnt;
dep[ch[u][str[i]-'a']]=dep[u]+1;
f[ch[u][str[i]-'a']][0]=u;
u=ch[u][str[i]-'a'];
for(int i=1;i<=16;i++) f[u][i]=f[f[u][i-1]][i-1];
}
v[pos]=u;
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=16;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=16;i>=0;i--)
{
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
}
return f[x][0];
}
}trie;
int main()
{
// freopen("biology.in","r",stdin);
// freopen("biology.out","w",stdout);
n=read();
m=read();
string t;
for(int i=1;i<=n;i++) cin>>t,trie.insert(reverse(t),i);
int op,x,y;
while(m--)
{
op=read();
if(op==1)
{
cin>>t;
trie.insert(reverse(t),++n);
}
else
{
x=read();
y=trie.v[read()];
for(int i=2;i<=x;i++)
{
y=trie.LCA(y,trie.v[read()]);
}
write(trie.dep[y]);
}
}
return 0;
}
/*
5 5
zzj
pri
prime
ime
owaski
2 3 1 3 5
2 2 2 3
1 actri
2 2 3 4
2 3 2 6 5
*/
Biology 题解的更多相关文章
- 题解 biology
传送门 赛时靠spfa求最长路骗了30pts spfa的时间复杂度是\(O(k|E|)\),不是\(O(k|N|)\)! dijkstra 时间复杂度\(O((n+m)logn)\) 特别注意这两个的 ...
- HDU 5590 ZYB's Biology 水题
ZYB's Biology Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...
- HDU1560 DNA sequence(IDA*)题解
DNA sequence Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- Biology(湖南集训)
题目大意:n个字符串,m个操作,可以插入字符串,也可以询问某T个字符串的最长后缀 题解:Trie+lca Trie树的插入与查询操作.把字符串反转就相当于求公共前缀. lca的深度就是公共前缀的长度. ...
- 遗传编程(GA,genetic programming)算法初探,以及用遗传编程自动生成符合题解的正则表达式的实践
1. 遗传编程简介 0x1:什么是遗传编程算法,和传统机器学习算法有什么区别 传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法.对于这些机器学习算法来说,唯一的灵活性体现在 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
随机推荐
- go的异常抛出
defer func() { if r := recover(); r != nil { fmt.Println("Recovered:", r) } }() 在任何涉及到数组取值 ...
- 移动端 web 调试神器 - Eruda
移动端 web 调试神器 - Eruda 移动端 web 调试神器 - Eruda 基本使用 效果预览 核心步骤 安装依赖 yarn add vite-plugin-html -D # or npm ...
- 使用Istio灰度发布
目录 灰度发布 1. Istio 1.1 Istio介绍 1.2 Istio是如何工作的 2. 安装Istio 2.1 环境 2.2 得到二进制文件 2.3 安装istio 3. 部署bookinfo ...
- openssl基础使用(密码学 linux)
目录 实验原理 实验过程 一.对称加密 1.使用rc4加解密 2.使用AES加解密 ...
- Electron 客户端开机自启动
app.setLoginItemSettings 与 auto-launch 对比分析 一.稳定性对比 1. app.setLoginItemSettings 优点:作为Electron官方API,有 ...
- Ubuntu22.04办公环境初始设置记录
1. 前言 这周末刚从Windows办公环境切换到 Ubuntu 22.04,有些东西还是比较折腾,记录一下便于以后查找. 2. 安装时的分区设置 从一块完整的新硬盘安装Ubuntu单系统时,只需要以 ...
- 0x00 语法知识
目录 C++ STL Vector Pair String Queue Stack Deque Set Map Bitset Algorithm库函数 Reverse Unique Random_sh ...
- DelayQueue的take方法底层原理
一.DelayQueue的take()方法底层原理 DelayQueue 的 take 方法是其核心方法之一,用于从队列中获取并移除延迟时间到期的元素.如果队列为空或没有延迟到期的元素,调用 take ...
- 🎀杜伽Durgod K610W蓝牙连接问题解决
简介 杜伽Durgod K610W键盘支持三模连接,在配对成功蓝牙后切换连接通道后,再次连接蓝牙通道时无法正常自动连接已配对的蓝牙,需取消配对再重新配对后才能正常连接.这种问题可以通过升级键盘固件解决 ...
- jmeter返回数据重新编码的方法
下图内容为请求后的返回值,红色箭头内容是需要正则处理传参给后面的接口使用 其中==后面的\U0026为未编码内容 而实际能够提交的链接为下图"&" 所以,图1请求后需要先转 ...