BZOJ5261 Rhyme
传送门
广义后缀自动机= =+
跟ptx大爷的博客学的 戳我传送
我写的第一种 建立Trie树的写法 bfs建立SAM
为什么是bfs呢 我也不知道(GG) 经过我一番抱大腿+询问 各位大爷说的原因是 因为dfs时间复杂度不对
多有道理哦 【摔
不过好像这个复杂度保证好像真的不大准确2333
所以 安安心心bfs就最吼啦 复杂度貌似是trie的大小
其实 每次重置last为rt也可以啊qwq 这个复杂度是字符串总长度的
那么这个题的做法就是 建立完SAM 然后 我们类似AC自动机一样建立类fail指针一样的东西
这个指针要保证len>=k 并且两个可以连接起来 也就是x向parent上跳 并且x和上面的串长都要是>=k的 然后找到有这个字符的地方链接就好啦
那么最后我们要求的就是这个新图的最长路
如果出现环了当然就是INF了qwq
附代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 20021225
#define ll long long
#define mxn 100010
using namespace std;
struct node{int fa,len,ch[26],c;};
struct edge{int to,lt;}e[mxn*20];
int cnt,in[mxn*4],k;
void add(int x,int y)
{
e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;
}
struct trie
{
node t[mxn];int rt,poi;
void init()
{
for(int i=1;i<=poi;i++) memset(t[i].ch,0,sizeof(t[i].ch)),t[i].fa=t[i].c=0;
rt=poi=1;
}
void insert(char *ch)
{
int n=strlen(ch),pos=rt;
for(int i=0;i<n;i++)
{
int tmp=ch[i]-'a';
if(!t[pos].ch[tmp])
t[pos].ch[tmp]=++poi,t[poi].fa=pos,t[poi].c=tmp;
pos=t[pos].ch[tmp];
}
}
}tr;
struct SAM
{
node t[mxn*4]; int poi,rt,lt[mxn*4];
queue<int> que;
void init()
{
memset(lt,0,sizeof(lt));
for(int i=1;i<=poi;i++) memset(t[i].ch,0,sizeof(t[i].ch)),t[i].fa=t[i].c=t[i].len=0;
poi=0;rt=++poi;
}
int insert(int c,int lt)
{
int p=lt,np=++poi; t[np].len=t[lt].len+1;
for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np;
if(!p){t[np].fa=rt;return np;}
int q=t[p].ch[c];
if(t[q].len==t[p].len+1){t[np].fa=q;return np;}
int nq=++poi; t[nq].len=t[p].len+1;
memcpy(t[nq].ch,t[q].ch,sizeof(t[q].ch));
t[nq].fa=t[q].fa; t[np].fa=t[q].fa=nq;
for(;p&&t[p].ch[c]==q;p=t[p].fa) t[p].ch[c]=nq;
return np;
}
void build()
{
init();
while(!que.empty()) que.pop();
for(int i=0;i<26;i++)
if(tr.t[rt].ch[i]) que.push(tr.t[rt].ch[i]);
lt[tr.rt]=rt;
while(!que.empty())
{
int pos=que.front(); que.pop();
//printf("%d \n",pos);
lt[pos]=insert(tr.t[pos].c,lt[tr.t[pos].fa]);
for(int i=0;i<26;i++)
if(tr.t[pos].ch[i]) que.push(tr.t[pos].ch[i]);
}
}
void makemap()
{
for(int i=1;i<=poi;i++)
if(t[i].len>=k)
{
for(int c=0;c<26;c++)
{
if(t[i].ch[c])
{
if(t[t[i].ch[c]].len>=k) add(t[i].ch[c],i);
}
else
{
int p=i;
while(p&&!t[p].ch[c]&&t[p].len>=k) p=t[p].fa;
int np=t[p].ch[c];// printf("%d %d %d %d\n",i,p,np,t[np].len);
if(p&&np&&t[p].len+1>=k) t[i].ch[c]=np,add(np,i);
}
}
}
}
void print()
{
for(int i=1;i<=poi;i++)
{
printf("id=%d:%d %d\n",i,t[i].fa,t[i].len);
for(int j=0;j<26;j++)
if(t[i].ch[j]) printf("*%d %d\n",j,t[i].ch[j]);
}
}
}sam;
int f[mxn*4]; bool vis[mxn*4];
char ch[mxn];
int search(int pos)
{
//printf("%d %d\n",pos,f[pos]);
if(vis[pos]) return f[pos]=inf;
if(~f[pos]) return f[pos];
f[pos]=sam.t[pos].len; vis[pos]=1;
for(int i=in[pos];i;i=e[i].lt)
{
int y=e[i].to; int tmp=search(y);
if(tmp==inf) return f[pos]=inf;
f[pos] = max(f[pos],tmp+1);
}
vis[pos]=0; return f[pos];
}
void init()
{
for(int i=1;i<=cnt;i++)
e[i].to=e[i].lt=0;
cnt=0;memset(in,0,sizeof(in));
memset(f,-1,sizeof(f));
memset(vis,0,sizeof(vis));
}
int main()
{
int t;
while(~scanf("%d%d",&t,&k))
{
init();
tr.init();//tr.rt=tr.poi=1;
while(t--)
{
scanf("%s",ch);
tr.insert(ch);
}
sam.build();
sam.makemap();
//sam.print();
int ans=k-1;
for(int i=1;i<=sam.poi;i++)
if(sam.t[i].len>=k&&f[i]==-1)
search(i);
for(int i=1;i<=sam.poi;i++) ans=max(ans,f[i]);
if(ans>=inf) printf("INF\n");
else printf("%d\n",ans);
}
return 0;
}
BZOJ5261 Rhyme的更多相关文章
- BZOJ2938 [Poi2000]病毒 和 BZOJ5261 Rhyme
[Poi2000]病毒 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码 ...
- Codeforces 792B. Counting-out Rhyme
B. Counting-out Rhyme time limit per test: 1 second memory limit per test: 256 megabytes input: stan ...
- [省选模拟]Rhyme
考的时候脑子各种短路,用个SAM瞎搞了半天没搞出来,最后中午火急火燎的打了个SPFA才混了点分. 其实这个可以把每个模式串长度为$K-1$的字符串看作一个状态,这个用字符串Hash实现,然后我们发现这 ...
- B. Counting-out Rhyme(约瑟夫环)
Description n children are standing in a circle and playing the counting-out game. Children are numb ...
- POJ1671 Rhyme Schemes
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 1776 Accepted: 984 Special Judge De ...
- 2019上海网络赛 F. Rhyme scheme 普通dp
Rhyme scheme Problem Describe A rhyme scheme is the pattern of rhymes at the end of each line of a p ...
- CodeForce-792B Counting-out Rhyme(模拟)
Counting-out Rhyme CodeForces - 792B 题意: n 个孩子在玩一个游戏. 孩子们站成一圈,按照顺时针顺序分别被标号为 1 到 n.开始游戏时,第一个孩子成为领导. 游 ...
- BZOJ5261 Rhyme--广义SAM+拓扑排序
原题链接,不是权限题 题目大意 有\(n\)个模板串,让你构造一个尽量长的串,使得这个串中任意一个长度为\(k\)的子串都是至少一个模板串的子串 题解 可以先看一下这道题 [POI2000]病毒 虽然 ...
- BZOJ 5261 Rhyme
思路 考虑一个匹配的过程,当一个节点x向后拼接一个c的时候,为了满足题目条件的限制,应该向suflink中最深的len[x]+1>=k的节点转移(保证该后缀拼上一个c之后,长度为k的子串依然属于 ...
随机推荐
- 2018年第九届山东省ACM省赛总结
去年打完区域赛之后,面对着两个队友都去找实习的情况,我自己对今年省赛还是有点慌的.不只一次的像我的队友说明自己很慌,但是老曹跟会长都说:“没事,慌啥!”前几场训练赛因为老曹跟秋洁有面试有时候只能一个人 ...
- 批量搞机(一):ansible简介、ansible安装
一.ansible简介 Ansible是2013年推出的一款IT自动化和DevOps软件,目前由Redhat已签署Ansible收购协议.其是基于Python研发,糅合了很多老运维工具的优点实现了批量 ...
- C#中给RICHTEXTBOX加上背景图片
在系统自带的RichTextBox中是无法给它设置背景图片,但是我们在某些场合可能需要给RichTextBox设置背景图片.那么怎么实现这一想法呢?经过研究发现通过其它巧妙的途径可以给RichText ...
- sql server查询结果复制出来,没有换行(存进去的数据是换行的)
https://stackoverflow.com/questions/53115490/how-to-correctly-insert-newline-in-nvarchar The problem ...
- python爬虫学习之路-遇错笔记-1
当在运行爬虫时同时开启了Fidder解析工具时(此爬虫并不是用于爬取手机端那内容,而是爬去电脑访问的网页时),访问目标站点会遇到以下错误: File "C:\Users\litao\AppD ...
- Linux 初始化系统 systemd - journald 日志
journalctl 中文手册 archlinux - journal systemd-journald 用于检索 systemd 的日志,是 systemd 自带的日志系统. 1. systemd- ...
- 网易新闻实战 --- flask,ORM, Ajax异步删除
项目概述: 包含功能: 前端-- 新闻首页 新闻分类页 新闻详情页 后端-- 后台新闻管理(列表,分页) 新增新闻 修改新闻 删除新闻(AJAX)
- JavaScript如何获得两点之间顺时针旋转的角度
接上回:如何用javascript中的canvas让图片自己旋转 既然能够制定角度让图片旋转,那么现在要做的是自动获得旋转的角度, 让图片能够随着鼠标的方向旋转,让人物能够面朝鼠标的方向: 源代码: ...
- 解决BootstrapTable设置height属性后,表格不对齐的问题
解决BootstrapTable设置height属性后,表格不对齐的问题 2018年03月06日 09:56:54 nb7474 阅读数 5920 一般在使用BootstrapTable 插件 ...
- CentOS7和Ubuntu18.10下运行Qt Creator出现cannot find -lGL的问题的解决方案
解决方法:缺少相应的opengl的库,需要安装opengl库 一.Ubuntu下解决Qt5.11.1 cannot find -lGL 有两种原因: 一种是没有按照libGL库,那么就安装: sudo ...