[BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
2017-01-31 11:13
483 查看
题意
∑len(Ti)+∑len(Tj)可以O(1)计算出来。
主要就是求lcp(Ti,Tj)
将字符串反过来,建立后缀自动机,parent树就是原串的后缀树,lcp就是对应节点的lca,树形DP。
这幅图来自一篇不错的后缀自动机讲解
#include <cstdio> #include <iostream> #include <cstring> #include <string> #define N 500010<<1 using namespace std; typedef long long ll; struct SAM_{ int next [26],fail ,stp ,p,cnt,t ,r ; ll f ,w ; SAM_(){p=cnt=1;} void Extend(int x){ x-='a'; int np=++cnt;stp[np]=stp[p]+1;w[np]=f[np]=1; while(p&&!next[p][x]) next[p][x]=np,p=fail[p]; if(!p) fail[np]=1; else{ int q=next[p][x]; if(stp[q]==stp[p]+1) fail[np]=q; else{ int nq=++cnt;stp[nq]=stp[p]+1; memcpy(next[nq],next[q],sizeof(next[q])); fail[nq]=fail[q]; fail[q]=fail[np]=nq; while(p&&next[p][x]==q) next[p][x]=nq,p=fail[p]; } } p=np; } void Samort(){ int i; for(i=0;i<=cnt;i++) t[i]=0; for(i=1;i<=cnt;i++) t[stp[i]]++; for(i=1;i<=cnt;i++) t[i]+=t[i-1]; for(i=1;i<=cnt;i++) r[t[stp[i]]--]=i; } void Solve(int n){ for(int i=cnt;i;i--)f[fail[r[i]]]+=f[r[i]]; ll Ans1=1ll*n*(n+1)/2*(n-1),Ans2=0; for(int i=1;i<=cnt;i++){ Ans2+=1ll*w[fail[i]]*stp[fail[i]]*f[i]; w[fail[i]]+=f[i]; } printf("%lld\n",Ans1-Ans2*2); } }SAM; char A ; int n; int main(){ scanf("%s",A+1);n=strlen(A+1); for(int i=n;i;i--) SAM.Extend(A[i]); SAM.Samort(); SAM.Solve(n); }
相关文章推荐
- quagga源码学习--BGP协议对等体连接tcp md5签名认证选项
- C语言数组初始化
- MySQL的初步使用(1)———基本的SQL语句的使用
- 理解Tomcat的classpath
- quagga源码学习--BGP协议创建对等体
- Hadoop相关文章索引(2)——Hadoop运维主题
- CCF201609-2 火车购票(100分)
- Ubuntu下搭建JavaEE开发环境
- Duilib中将GDI换成GDI+
- 剑指offer——字符串的排列
- ioremap_nocache() 函数的使用
- Qt入门之基础篇 ( 二 ) :Qt项目建立、编译、运行和发布过程解析
- 小明的烦恼
- Android中事件处理机制之——ViewGroup的事件传递详解(一)
- python的Tqdm模块
- Rust 变量与函数
- SDL 显示bmp图片
- Cookie、Session 与 application
- leetcode - 33. Search in Rotated Sorted Array
- 直接拷贝数据文件实现Oracle数据迁移