Cool Slogans[CF700E][后缀自动机][Dp]
文章目录
- 题目
- 思路
- 代码
题目
Luogu
n ≤ 2 ⋅ 1 0 5 n\le 2\cdot 10^5 n≤2⋅105
思路
性质: ∃ s i \exist\quad s_i ∃si 是 s i − 1 s_{i-1} si−1 的后缀
如图
那么此时可以缩短 s i − 1 s_{i-1} si−1
然后联系后缀自动机不难想到是祖先关系
设 s i − 1 s_{i-1} si−1 代表结点为 u u u
设 s i s_{i} si 代表结点为 v v v
有 e n d p o s ( v ) ∈ e n d p o s ( u ) endpos(v)\in endpos(u) endpos(v)∈endpos(u)
由于是后缀,必定出现一次
现在还要找一次
如图,黑色的是 e n d p o s ( v ) endpos(v) endpos(v) 所有的是 e n d p o s ( u ) endpos(u) endpos(u)
那么任意找一个 x ∈ e n d p o s ( v ) x\in endpos(v) x∈endpos(v) 后找 [ x − m a x l e n v + m a x l e n u , x − 1 ] [x-maxlen_v+maxlen_u,x-1] [x−maxlenv+maxlenu,x−1] 中出现一个即可
线段树合并即可
代码
//#pragma GCC optimize(2)
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<cstdio>
#include<queue>
#include<cmath>
#include<vector>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
int read(){int f=1,x=0;char c=getchar();while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}return f*x;
}
#define MAXN 600000
#define INF 0x3f3f3f3f
int ed[MAXN+5];
int Root,scnt,lst,maxlen[MAXN+5],nxt[MAXN+5][27],fail[MAXN+5];
int Newnode(){int u=++scnt;fail[u]=0,maxlen[u]=0;memset(nxt[u],0,sizeof(nxt[u]));return u;
}
void Init(){scnt=0;Root=lst=Newnode();return ;
}
void Extend(int c,int id){int p=lst,cur=(lst=Newnode());ed[cur]=id;maxlen[cur]=maxlen[p]+1;while(p&&!nxt[p][c])nxt[p][c]=cur,p=fail[p];if(!p){fail[cur]=1;return ;}int q=nxt[p][c];if(maxlen[q]==maxlen[p]+1){fail[cur]=q;return ;}int clone=Newnode();ed[clone]=id;maxlen[clone]=maxlen[p]+1;memcpy(nxt[clone],nxt[q],sizeof(nxt[q]));fail[clone]=fail[q];fail[cur]=fail[q]=clone;while(p&&nxt[p][c]==q)nxt[p][c]=clone,p=fail[p];return ;
}
int ncnt,rt[MAXN+5],ch[25*MAXN+5][2];
void Insert(int &u,int L,int R,int p){u=++ncnt;if(L==R)return ;int Mid=(L+R)>>1;if(p<=Mid)Insert(ch[u][0],L,Mid,p);else Insert(ch[u][1],Mid+1,R,p);return ;
}
int Merge(int u,int v){if(!u||!v) return u|v;int p=++ncnt;ch[p][0]=Merge(ch[u][0],ch[v][0]);ch[p][1]=Merge(ch[u][1],ch[v][1]);return p;
}
int n;
vector<int> G[MAXN+5];
void DFS(int u){if(ed[u])Insert(rt[u],1,n,ed[u]);for(int i=0;i<(int)G[u].size();i++){int v=G[u][i];DFS(v);rt[u]=Merge(rt[u],rt[v]);}return ;
}
int ans,f[MAXN+5],fa[MAXN+5];
bool Query(int u,int L,int R,int qL,int qR){if(!u) return 0;if(qL<=L&&R<=qR)return 1;int Mid=(L+R)>>1;if(qL<=Mid)if(Query(ch[u][0],L,Mid,qL,qR))return 1;if(Mid+1<=qR)if(Query(ch[u][1],Mid+1,R,qL,qR))return 1;return 0;
}
void DP(int u){for(int i=0;i<(int)G[u].size();i++){int v=G[u][i];if(u==Root)f[v]=1,fa[v]=v;else{if(Query(rt[fa[u]],1,n,ed[v]-maxlen[v]+maxlen[fa[u]],ed[v]-1))f[v]=f[fa[u]]+1,fa[v]=v;else f[v]=f[fa[u]],fa[v]=fa[u];}ans=max(ans,f[v]);DP(v);}return ;
}
char S[MAXN+5];
int main(){n=read();scanf("%s",S+1);Init();for(int i=1;i<=n;i++)Extend(S[i]-'a'+1,i);for(int i=2;i<=scnt;i++)G[fail[i]].push_back(i);DFS(Root);DP(Root);printf("%d\n",ans);return 0;
}
Cool Slogans[CF700E][后缀自动机][Dp]相关推荐
- 【CF700E】Cool Slogans【后缀自动机】【可持久化线段树合并】【树上倍增】
传送门 题意:给定字符串SSS,求一堆字符串s1,s2,s3,...,sks_1,s_2,s_3,...,s_ks1,s2,s3,...,sk,满足s1s_1s1是SSS的子串,且sis_i ...
- hdu5343 后缀自动机+dp
给定两个串,分别截取字串X和Y,连接组成X+Y,求不同的X+Y的方案数. 对于X+Y,如果重复的部分其实就是从同一个X+Y的某个地方断开弄成不同的X和Y,那么只要使得X和X+Y匹配得最长就行了. 因此 ...
- BZOJ2806(后缀自动机+DP)
题目:http://61.187.179.132/JudgeOnline/problem.php?id=2806 题意:给定一个由M个01串组成的字典.依据这个字典和一个阀值L,可以断言一个01串是否 ...
- 洛谷P3975【天津省选2015】(后缀自动机DP)
题目链接 https://www.luogu.com.cn/problem/P3975 题解 此题非常经典且重要,是sam的函谷关,必须拿下. 记录每个点endpos大小的方法是在parent树从下往 ...
- 后缀自动机+DP BZOJ 3238 差异
分析: 其实题目就是要求任意两个后缀T[i]和T[j] (i< j) 的 LCP长度之和. 首先对输入的字符串反转后建立SAM. 令 一个节点的Max表示它代表的最长子串. 推论1: 原串中的两 ...
- BZOJ-3473 (广义后缀自动机:拓扑 or 启发式合并)
BZOJ-3473 (广义后缀自动机:拓扑 or 启发式合并) 题目链接 题意 nnn个字符串,询问每个字符串一共有几个子串至少出现在nnn个字符串中的kkk个 思路: 拓扑 建广义后缀自动机, dp ...
- SPOJ 7258 (后缀自动机)
转载:http://hzwer.com/4492.html 给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 搞出后缀自动机 dp处理出每个点往下走能 ...
- BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806 (luogu) https://www.luogu.org/pro ...
- BZOJ 4032 luogu P4112 [HEOI2015]最短不公共子串 (DP、后缀自动机)
这其实是道水题... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4032 (luogu)https://www.luog ...
最新文章
- PAT(甲级)2019年冬季考试 7-4 Cartesian Tree
- crontab 总结
- 从Visual Studio里抓取抽象语法树(AST)
- 计算机作文1500字,写科技的作文1500字
- The Geometry has no Z values 解决办法(转载)
- 二叉树的几种递归和非递归式遍历:
- .net core HttpClient 使用之掉坑解析(一)
- Flask 蓝图,数据库链接
- 一个 Java 的 Socket 服务器和客户端通信的例子
- 详解Paint的setColorFilter(ColorFilter filter)
- ArcGIS API for Silverlight 调用GP服务绘制等值面
- ASP实现AJAX的几种方式!
- nuke软件功能有哪些?苹果Mac影视后期特效合成软件NUKE 13
- 用java写一个贪吃蛇小游戏(源码在最后)
- 防御 DDoS 的终极奥义——又拍云 SCDN
- linux安装微信 安装百度网盘 下载大文件
- 代理ip按功能分哪几类?
- centos安装uWSGI失败处理办法Exception: you need a C compiler to build uWSGI
- IETester汉化文件下载
- 世界互联网大会为什么把这么重要的奖颁给蚂蚁金服?
热门文章
- abiFilters
- vue中如何使用echarts——以折线图为例
- Windows Server 2012 R2 详细安装步骤
- web项目答辩总结_java web 答辩总结
- n级lfsr输出m序列c语言,第2章流密码(LFSR)
- C程序中的#line意义何在
- 【英语思维导图制作】万彩脑图大师教程 | 插入表情
- Kettle数据的导入导出—批量Excel表到数据库
- 福建省c语言等级考试成绩查询,福建省高校计算机等级考试成绩查询
- 【Leetcode】213. 打家劫舍II(House Robber II)