BZOJ 5261 Rhyme
思路
考虑一个匹配的过程,当一个节点x向后拼接一个c的时候,为了满足题目条件的限制,应该向suflink中最深的len[x]+1>=k的节点转移(保证该后缀拼上一个c之后,长度为k的子串依然属于模板串的子串),然后拓扑求最长链即可,出现环就输出INF
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int Nodecnt,trans[250000][26],suflink[250000],maxlen[250000],n,k;
char s[250000];
int New_state(int _maxlen,int *_trans,int _suflink){
++Nodecnt;
maxlen[Nodecnt]=_maxlen;
if(_trans)
for(int i=0;i<26;i++)
trans[Nodecnt][i]=_trans[i];
suflink[Nodecnt]=_suflink;
return Nodecnt;
}
int add_len(int u,int c){
if(trans[u][c]){
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
return v;
}
int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[v]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return y;
}
else{
int z=New_state(maxlen[u]+1,NULL,0);
while(u&&trans[u][c]==0){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[z]=suflink[v]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
}
int in[250000],use[250000],v[250000],nxt[250000],fir[250000],cnt,dp[250000];
void init(void){
Nodecnt=1;
memset(trans,0,sizeof(trans));
memset(suflink,0,sizeof(suflink));
memset(maxlen,0,sizeof(maxlen));
memset(in,0,sizeof(in));
memset(use,0,sizeof(use));
cnt=0;
memset(v,0,sizeof(v));
memset(nxt,0,sizeof(nxt));
memset(fir,0,sizeof(fir));
memset(dp,0,sizeof(dp));
}
void addedge(int ui,int vi){
++cnt;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
void dfs(int u){
if(use[u]){
for(int i=0;i<26;i++){
if(trans[u][i]&&use[trans[u][i]])
in[trans[u][i]]++;
else{
int p=u;
while(p&&(trans[p][i]==0||maxlen[p]+1<k))
p=suflink[p];
trans[u][i]=trans[p][i];
in[trans[p][i]]++;
}
}
for(int i=fir[u];i;i=nxt[i])
dfs(v[i]);
}
else
for(int i=fir[u];i;i=nxt[i])
dfs(v[i]);
}
queue<int> q;
int topu(void){
while(!q.empty())
q.pop();
for(int i=1;i<=Nodecnt;i++)
use[i]=(maxlen[i]>=k),addedge(suflink[i],i);
dfs(1);
int num=0;
for(int i=1;i<=Nodecnt;i++){
num+=use[i];
if(use[i]&&(!in[i]))
q.push(i),dp[i]=maxlen[i];
}
if(!num)
return k-1;
if(q.empty())
return 0x3f3f3f3f;
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=0;i<26;i++){
if(trans[x][i]){
dp[trans[x][i]]=max(dp[trans[x][i]],dp[x]+1);
in[trans[x][i]]--;
if(!in[trans[x][i]])
q.push(trans[x][i]);
}
}
}
int ans=0;
for(int i=1;i<=Nodecnt;i++)
if(use[i]&&in[i])
return 0x3f3f3f3f;
else
ans=max(ans,dp[i]);
return ans;
}
int main(){
while(scanf("%d %d",&n,&k)==2){
init();
for(int i=1;i<=n;i++){
scanf("%s",s+1);
int len=strlen(s+1),last=1;
for(int j=1;j<=len;j++)
last=add_len(last,s[j]-'a');
}
int t=topu();
if(t==0x3f3f3f3f){
printf("INF\n");
}
else{
printf("%d\n",t);
}
}
return 0;
}
BZOJ 5261 Rhyme的更多相关文章
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
- BZOJ 题目整理
bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
- 【清华集训】楼房重建 BZOJ 2957
Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...
- 【splay】文艺平衡树 BZOJ 3223
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...
- bzoj 刷水
bzoj 3856: Monster 虽然是sb题,,但是要注意h可能<=a,,,开始忘记判了WA得很开心. #include <iostream> #include <cst ...
随机推荐
- Spark入门到精通--(第九节)环境搭建(Hive搭建)
上一节搭建完了Hadoop集群,这一节我们来搭建Hive集群,主要是后面的Spark SQL要用到Hive的环境. Hive下载安装 下载Hive 0.13的软件包,可以在百度网盘进行下载.链接: h ...
- 在linux系统中出现u盘问题 的相关解决方法
1.显示unknown filesystem type .exfat 可以通过该方法解决: 安装exfat-fuse: 在终端中以管理员身份运行 sudo apt-get install exfat- ...
- linux 几种服务类型
采集来自于 https://blog.csdn.net/hguisu/article/details/7453390 https://blog.csdn.net/limo120621/article/ ...
- MongoDB系列----备份与导入导出
参考: http://my.oschina.net/xiaomaoandhong/blog/63471,<> 1.停掉服务器 然后备份 Mongodb将所有数据都存放在"数据目录 ...
- python爬虫简单的添加代理进行访问
在使用python对网页进行多次快速爬取的时候,访问次数过于频繁,服务器不会考虑User-Agent的信息,会直接把你视为爬虫,从而过滤掉,拒绝你的访问,在这种时候就需要设置代理,我们可以给proxi ...
- Python:re中的group方法简介
原文地址:http://www.cnblogs.com/kaituorensheng/archive/2012/08/20/2648209.html. 正则表达式中,group()用来提出分组截获的字 ...
- C# 链表反转
链表反转分这么两种情况, 一种是链表头节点始终前置,那这时候需要传一个头节点特有的标记:(简称:头不转) HEAD->Test1->Test2->Test3->Test4 反转 ...
- NetCore +EF+Mysql 从数据库生成实体类到项目
1.点击“工具”->“NuGet包管理器”->“程序包管理器控制台” 分别安装以下几个包 Mysql 版本: Install-Package MySql.Data.EntityFramew ...
- redis的 rdb 和 aof 持久化的区别
aof,rdb是两种 redis持久化的机制.用于crash后,redis的恢复. rdb的特性如下: Code: fork一个进程,遍历hash table,利用copy on write,把整个d ...
- python学习笔记之socket(第七天)
参考文档: 1.金角大王博客:http://www.cnblogs.com/alex3714/articles/5227251.html ...