博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj4566: [Haoi2016]找相同字符
阅读量:4599 次
发布时间:2019-06-09

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

一个串建SAM,一个串在上面跑DP

需要注意,走到当前节点的时候,有可能走的是近路,并不能把当前节点表示的所有子串匹配,这个时候就要记录一下走的步数(类似caioj那题),那些被当前点表示的,长度不超过步数的子串才有资格更新答案。

这个东西我用g来维护

然后他去更新其他人就没有这个限制了,用h表示覆盖的次数,减去f表示直接走到的次数,然后乘上这个点代表的子串数和出现次数,就是其他人更新我的答案

g和这个东西加起来就是答案了

#include
#include
#include
#include
#include
#include
using namespace std;typedef long long LL;int a[210000],len;struct SAM{ int w[30],dep,fail;}ch[410000];int last,cnt;void insert(int dep,int x){ int pre=last,now=++cnt; ch[now].dep=dep; last=now; while(pre!=0&&ch[pre].w[x]==0) ch[pre].w[x]=now, pre=ch[pre].fail; if(pre==0)ch[now].fail=1; else { int nxt=ch[pre].w[x]; if(ch[nxt].dep==ch[pre].dep+1)ch[now].fail=nxt; else { int nnxt=++cnt; ch[nnxt]=ch[nxt]; ch[nnxt].dep=ch[pre].dep+1; ch[nxt].fail=ch[now].fail=nnxt; while(pre!=0&&ch[pre].w[x]==nxt) ch[pre].w[x]=nnxt, pre=ch[pre].fail; } }}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~init~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~int T,Right[410000];//根到当前节点组成的子串(当前节点管理的子串)出现次数,当前节点管理的子串数=ch[x].dep-ch[ch[x].fail].depint Rsort[410000],sa[410000];void GetRight(){ memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=cnt;i++)Rsort[ch[i].dep]++; for(int i=1;i<=len;i++)Rsort[i]+=Rsort[i-1]; for(int i=cnt;i>=1;i--)sa[Rsort[ch[i].dep]--]=i; int now=1; memset(Right,0,sizeof(Right)); for(int i=1;i<=len;i++) now=ch[now].w[a[i]], Right[now]++; for(int i=cnt;i>=1;i--) { int u=sa[i],v=ch[u].fail; Right[v]+=Right[u]; } Right[1]=0;}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//------------------------------------------------------SAM-----------------------------------------------------------------LL f[410000],g[410000],h[410000];void solve(){ int now=1,L=0; memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); memset(h,0,sizeof(h)); for(int i=1;i<=len;i++) { int x=a[i]; while(now!=1&&ch[now].w[x]==0) now=ch[now].fail, L=ch[now].dep; if(ch[now].w[x]!=0) { L++; now=ch[now].w[x]; f[now]++,h[now]++; g[now]+=Right[now]*(L-ch[ch[now].fail].dep); } } for(int i=cnt;i>=1;i--) { int u=sa[i],v=ch[u].fail; f[v]+=f[u]; } LL ans=0; for(int i=2;i<=cnt;i++)ans+=g[i]+(f[i]-h[i])*Right[i]*(ch[i].dep-ch[ch[i].fail].dep); printf("%lld\n",ans);}char ss[210000];int main(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%s",ss+1);len=strlen(ss+1); last=cnt=1; ch[1].dep=0; for(int i=1;i<=len;i++) a[i]=ss[i]-'a'+1, insert(i,a[i]); GetRight(); scanf("%s",ss+1);len=strlen(ss+1); for(int i=1;i<=len;i++)a[i]=ss[i]-'a'+1; solve(); return 0;}

 

 

转载于:https://www.cnblogs.com/AKCqhzdy/p/10053632.html

你可能感兴趣的文章
将数据库所有表和字段首字母变成大写
查看>>
如何在vue项目中使用md5.js及base64.js
查看>>
最长公共子序列 Lcs
查看>>
关于虚拟空间上传没有权限问题 只要更改一下system.web 就可以
查看>>
C#知识点总结【1】
查看>>
BZOJ 1257: [CQOI2007]余数之和
查看>>
20155235 2016-2017-2 《Java程序设计》第六周学习总结
查看>>
H3C VLAN 配置
查看>>
BZOJ 1077: [SCOI2008]天平
查看>>
第一天
查看>>
团队冲刺第十天
查看>>
Gradle用户指南
查看>>
iOS审核策略重磅更新:Guideline 2.1批量拒审
查看>>
给 vue项目添加ESLint
查看>>
Swift3.0 功能一(持续更新)
查看>>
HexColor
查看>>
Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
查看>>
你会用swift创建复杂的加载动画吗(1)
查看>>
javabean转换为map对象
查看>>
CSS从入门到精通2.md
查看>>