博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1396 识别子串
阅读量:6360 次
发布时间:2019-06-23

本文共 2274 字,大约阅读时间需要 7 分钟。

拼命给自己拉低AC率(

SAM 一发入魂

很明显 我们要查的就是 叶子结点

叶子结点 的 len 和 其父亲的 len 会影响一段区间

大概长这个样子 前面一段倾斜的 就是 len 在不断增长 后面的要取min所以就是平直的[你可能需要意会一下]

因为一个点的len是一段连续的区间 你从这个图里就可以看的比较清楚了qwq

然后我们 就重锤李超树 咳咳咳才不要李超树呢 我们发现 所有的斜线都是斜率为-1 那么我们对于斜线维护 ai+i 最后-i 就变成了直线

现在就是两种直线 我们分别用两棵线段树维护就好了

(注意:SAM中叶子节点一定是 “关键节点”[前缀节点] 而“关键节点”不一定全部都是叶子结点)

附代码。

#include
#include
#include
#include
#define inf 20021225#define ll long long#define mxn 100010#define ls(x) x<<1#define rs(x) x<<1|1using namespace std;int ans[mxn];struct segtree{ int mn[mxn*4],tag[mxn*4]; void pushdown(int x) { if(tag[x]
>1; build(ls(x),l,mid);build(rs(x),mid+1,r); } void modify(int x,int l,int r,int LL,int RR,int val) { if(RR
=LL&&r<=RR) { mn[x] = min(mn[x],val); tag[x] = min(tag[x],val); return; } int mid=l+r>>1; pushdown(x); if(LL<=mid) modify(ls(x),l,mid,LL,RR,val); if(RR>mid) modify(rs(x),mid+1,r,LL,RR,val); pushup(x); } void query(int x,int l,int r) { if(l==r){ans[l]=mn[x];return;} int mid = l+r>>1; pushdown(x); query(ls(x),l,mid); query(rs(x),mid+1,r); }}t1,t2;struct node{int fa,len,ch[26];}t[mxn*4];int poi,rt,lt; char ch[mxn];int pos[mxn],n;void init(){ rt=lt=++poi; t1.build(1,1,n); t2.build(1,1,n);}int id(char c){return c-'a';}bool vis[mxn*4];void insert(int c,int id){ int p=lt,np=lt=++poi; t[np].len=t[p].len+1; pos[id]=np; for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np; if(!p){t[np].fa=rt;return;} int q=t[p].ch[c]; if(t[q].len==t[p].len+1){t[np].fa=q; vis[q] =1;return;} 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[q].fa=t[np].fa=nq; vis[nq] = 1; for(;p&&t[p].ch[c]==q;p=t[p].fa) t[p].ch[c]=nq;}int f[mxn];void calc(){ for(int i=1;i<=n;i++) { int x=pos[i],f=t[x].fa; if(vis[x]) continue; int l2=t[x].len,l1=t[f].len+1; t1.modify(1,1,n,i-l1+1,i,l1); t2.modify(1,1,n,i-l2+1,i-l1,i+1); } t1.query(1,1,n); memcpy(f,ans,sizeof(f)); //for(int i=1;i<=n;i++) printf("%d ",ans[i]); t2.query(1,1,n); for(int i=1;i<=n;i++) ans[i]-=i,f[i]=min(f[i],ans[i]); for(int i=1;i<=n;i++) printf("%d\n",f[i]);}int main(){ scanf("%s",ch+1); n=strlen(ch+1); init(); for(int i=1;i<=n;i++) insert(id(ch[i]),i); calc(); return 0;}

 

转载于:https://www.cnblogs.com/hanyuweining/p/10321908.html

你可能感兴趣的文章
ORM框架Hibernate (四)MyEclipse Hibernate Tool 逆向生成实体类
查看>>
去掉iphone连接电脑时会出现的弹出窗口
查看>>
【python】-- web开发之HTML
查看>>
vs2015 去除 git 源代码 绑定
查看>>
解决firefox的button按钮文字不能垂直居中
查看>>
网络协议端口号详解
查看>>
大话数据结构读后感——第一章
查看>>
各种排序
查看>>
Optional
查看>>
sed 命令编辑文本
查看>>
Activity调用isDestroyed()方法报出,java.lang.NoSuchMethodError
查看>>
Keepalived详解(四):通过vrrp_script实现对集群资源的监控【转】
查看>>
CollapsingToolbarLayoutDemo【可折叠式标题栏,顺便带有CardView卡片式布局】
查看>>
CentOS7.4安装配置mysql5.7 TAR免安装版
查看>>
解决IE二级链接无法打开故障
查看>>
Windows phone应用开发[16]-数据加密
查看>>
通用数据压缩算法简介
查看>>
The next Industry Standard in IT Monitoring, a python implementation Nagios like tool --- Shinken
查看>>
(笔记)找工作,该怎么进补
查看>>
div的显示和隐藏以及点击图标的更改
查看>>