LINK:波波老师

LINK:同bzoj 1396 识别子串

不过前者要求线性做法 后者可以log过。实际上前者也被我一个log给水过了.

其实不算很水 我自认跑的很快罢了.

都是求经过一个位置的最短的 在整个字符串中只出现过一次的子串。

SAM很容易完成这个东西.

考虑对于计算每个节点的贡献 容易发现是一个区间整体赋值和一个等差数列 不过太懒了不想维护这个等差数列 我反着建SAM维护最右左端点了。

就变成了两个区间最值问题。完全可以标记永久化 可能有点卡空间。

当然考场上也思考了O(n)的做法 先考虑等差数列那个地方 由于right集大小为1 那么显然这个点的len是一直到之后都有效所以可以直接标记最后取max

考虑区间取min操作。当时想法是排序后利用并查集 排列可以利用桶排 然后复杂度就降到\(n\cdor (a)\)

可以发现桶排序之后可以利用单调队列+链表 来实现O(n).细节有点繁琐 不再赘述.

标记永久化还是很快滴 (比其他dalao写zkw线段树要快一点.当时我也想写zkw线段树 不过不太熟练所以就没用

const int MAXN=5000010;
int n,cnt=1,last=1;
int sum[MAXN<<2],w[MAXN<<2];//一个取max 一个取min.
struct wy
{
int ch[5];
int fa,len;
}t[MAXN<<1];
char a[MAXN];ll ans;
int c[MAXN],vis[MAXN<<1],s[MAXN<<1];
inline void insert(int x)
{
int p=last;
int np=last=++cnt;
len(np)=len(p)+1;
while(p&&!t[p].ch[x])
{
t[p].ch[x]=np;
p=f(p);
}
if(!p)f(np)=1;
else
{
int q=t[p].ch[x];
if(len(q)==len(p)+1)f(np)=q;
else
{
int nq=++cnt;
t[nq]=t[q];
len(nq)=len(p)+1;
f(np)=f(q)=nq;
while(p&&t[p].ch[x]==q)
{
t[p].ch[x]=nq;
p=f(p);
}
}
}
}
inline void topsort()
{
rep(1,cnt,i)++c[len(i)];
rep(1,n,i)c[i]+=c[i-1];
rep(1,cnt,i)s[c[len(i)]--]=i;
}
inline void change(int p,int l,int r,int L,int R,int x)
{
if(l==L&&r==R)return sum[p]=min(sum[p],x),void();
int mid=(l+r)>>1;
if(L>mid)return change(yy,mid+1,r,L,R,x),void();
if(R<=mid)return change(zz,l,mid,L,R,x),void();
change(zz,l,mid,L,mid,x);change(yy,mid+1,r,mid+1,R,x);
}
inline void modify(int p,int l,int r,int L,int R,int x)
{
if(l==L&&r==R)return w[p]=max(w[p],x),void();
int mid=(l+r)>>1;
if(L>mid)return modify(yy,mid+1,r,L,R,x),void();
if(R<=mid)return modify(zz,l,mid,L,R,x),void();
modify(zz,l,mid,L,mid,x);modify(yy,mid+1,r,mid+1,R,x);
}
inline void dfs(int p,int l,int r,int S,int W)
{
S=min(S,sum[p]);W=max(W,w[p]);
if(l==r)
{
if(W==0)W=-INF;
ans+=min(S,l-W+1);
return;
}
int mid=(l+r)>>1;
dfs(zz,l,mid,S,W);
dfs(yy,mid+1,r,S,W);
}
int main()
{
freopen("bobo.in","r",stdin);
freopen("bobo.out","w",stdout);
gc(a);n=strlen(a+1);
fep(n,1,i)insert(a[i]-'a'),vis[last]=i;
topsort();
memset(sum,0x3f,sizeof(sum));
fep(cnt,2,i)
{
int x=s[i];
//cout<<vis[x]<<' '<<len(x)<<endl;
if(vis[x]==-1)vis[f(x)]=-1;
else
{
if(!vis[f(x)])vis[f(x)]=vis[x];
else vis[f(x)]=-1;
}
if(vis[x]!=-1)
{
change(1,1,n,vis[x],vis[x]+len(f(x)),len(f(x))+1);
modify(1,1,n,vis[x]+len(f(x)),vis[x]+len(x)-1,vis[x]);
}
}
dfs(1,1,n,INF,0);putl(ans);
return 0;
}

5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集的更多相关文章

  1. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  2. 6.29 省选模拟赛 坏题 AC自动机 dp 图论

    考场上随手构造了一组数据把自己卡掉了 然后一直都是掉线状态了. 最后发现这个东西不是subtask -1的情况不多 所以就没管无解直接莽 写题有点晚 故没调出来.. 考虑怎么做 容易想到建立AC自动机 ...

  3. 5.29 省选模拟赛 树的染色 dp 最优性优化

    LINK:树的染色 考场上以为这道题要爆蛋了 没想到 推出正解来了. 反正是先写了爆搜的 爆搜最近越写越熟练了 容易想到dp 容易设出状态 f[i][j]表示以i为根的子树内白色的值为j此时黑色的值怎 ...

  4. 3.29省选模拟赛 除法与取模 dp+组合计数

    LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...

  5. 4.9 省选模拟赛 划分序列 二分 结论 树状数组优化dp

    显然发现可以二分. 对于n<=100暴力dp f[i][j]表示前i个数分成j段对于当前的答案是否可行. 可以发现这个dp是可以被优化的 sum[i]-sum[j]<=mid sum[i] ...

  6. 6.18 省选模拟赛 字符串 LCT SAM

    LINK:字符串 看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子. 期望得分10分.实际得分10分. 另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳. 期望得分1 ...

  7. 4.24 省选模拟赛 欧珀瑞特 主席树 可持久化trie树

    很容易的一道题目.大概.不过我空间计算失误MLE了 我草草的计算了一下没想到GG了. 关键的是 我学了一个dalao的空间回收的方法 但是弄巧成拙了. 题目没有明确指出 在任意时刻数组长度为有限制什么 ...

  8. 2018-8-10 模拟赛T3(可持久化线段树)

    出题人说:正解离线按DFS序排序线段维护区间和 但是对于树上每个点都有一个区间和一个值,两个点之间求1~m的区间和,这不就是用可持久化线段树吗. 只不过这个线段树需要区间修改,不过不需要标记下传,询问 ...

  9. 7.18 NOI模拟赛 因懒无名 线段树分治 线段树维护直径

    LINK:因懒无名 20分显然有\(n\cdot q\)的暴力. 还有20分 每次只询问一种颜色的直径不过带修改. 容易想到利用线段树维护直径就可以解决了. 当然也可以进行线段树分治 每种颜色存一下直 ...

随机推荐

  1. request.headers.get头部获取内容的缺失

    1.说明 今天遇到了一个小坑,在做权限控制的时候,用头部传递了参数取名为table_privilege_id, 在本地测试的时候是可以接到这个参数的,但是通过ngxin转发之后,奇怪了,怎么也拿不到这 ...

  2. TKCTF-学校内部的校赛

    *Reverse easy_C easy_re1.exe 在网络百度到解决逆向需要用到软件IDA 然后用IDA打开一条条的找我找到了一条很怪的ZmxhZ3s1ZWU1ZjYyOC1mMzVhLTQxN ...

  3. java动态代理基本原理及proxy源码分析一

    本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的态度,于是对java动态代理的本质原理做了一些研究,于是便有了这个系列的文章 为了尽快进入正题,这里 ...

  4. java学习第三天2020/7/8

    一. 学习了数组的使用 一维数组的使用 (1)类型[ ] 名称 名称=new 类型[]{元素1,元素2......} (2)类型[] 名称={元素1,元素2......} (3)类型[] 名称=new ...

  5. day18 作业

    目录 1.编写课上讲解的有参装饰器准备明天默写 2.在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作 3.编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017- ...

  6. python 装饰器(八):装饰器基础(四)types.MethodType的作用

    1 types.MethodType的作用—添加实例方法 import types class cla(object): def __init__(self, name, age): self.nam ...

  7. css 实现动态二级菜单

    动态实现简单的二级菜单 当鼠标放到一级标签上时,鼠标会变成小手的形状 展示二级菜单,源码如下,复制即可直接使用 <!DOCTYPE html> <html lang="en ...

  8. 1.对Java平台的理解。“Java是解释执行”对吗

    Java本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”,能够非常容易地获得跨平台能力: 另外就是垃圾收集(GC),Java通过垃圾收集器(Garbage Colle ...

  9. Java常用API(Arrays类)

    Java常用API(Arrays类) 什么是Arrays类? java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等.其所有方法均为静态方法,调用起来 非常简单. 这里我们 ...

  10. OSCP Learning Notes - WebApp Exploitation(5)

    Remote File Inclusion[RFI] Prepare: Download the DVWA from the following website and deploy it on yo ...