bzoj 3238 差异
来源:互联网 发布:网络商业计划书 编辑:程序博客网 时间:2024/06/07 10:24
给出一个长n的字符集为小写字母的字符串,求
如果我们拥有这个字符串的后缀树,将每个后缀所对应的节点记为标记点。
对每一个标记点对,我们统计的其实是这两个点到根的距离和减去根到他们
那我们要求的实际上就是树上所有标记点对的距离和。
以下不加证明的给出一个结论
一个字符串翻转的后缀自动机的
有了上面那个结论之后我们就可以用
#include<bits/stdc++.h>using namespace std;const int maxn = 512345,mlen = 26;#define LL long long LL ans;LL dp[maxn*2],siz[maxn*2];vector<pair<int,int> >edge[maxn*2];void Link(int st,int ed,int v){ edge[st].push_back(make_pair(ed,v)); edge[ed].push_back(make_pair(st,v));}struct Sam{ int len[maxn*2],fa[maxn*2],nex[maxn*2][mlen]; int val[maxn*2]; int _cnt,root,omg; int newNode(int L = 0){ len[_cnt] = L; memset(nex[_cnt],fa[_cnt] = -1,sizeof(nex[_cnt])); return _cnt++; } void init(){ _cnt = 0; memset(val,0,sizeof(val)); root = omg = newNode(); } void extend(int x){ int ox = newNode(len[omg]+1); val[ox]++; while(omg != -1 && nex[omg][x] == -1){ nex[omg][x] = ox; omg = fa[omg]; } if(omg == -1) fa[ox] = root; else{ int omgx = nex[omg][x]; if(len[omgx] == len[omg]+1) fa[ox] = omgx; else{ int mgx = newNode(len[omg]+1); for(int i=0;i<mlen;i++) nex[mgx][i] = nex[omgx][i]; fa[mgx] = fa[omgx]; fa[omgx] = fa[ox] = mgx; while(omg != -1 && nex[omg][x] == omgx) nex[omg][x] = mgx,omg = fa[omg]; } } omg = ox; } void build(char *arr){ init(); for(int i=0;arr[i];i++){ extend(arr[i] - 'a'); } } void treeBuild(){ for(int i=0;i<_cnt;i++){ edge[i].clear(); dp[i] = 0 , siz[i] = val[i]; } for(int i=0;i<_cnt;i++){ if(fa[i] != -1){ Link(i,fa[i],len[i] - len[fa[i]]); } } }}SAM;char arr[maxn];void dfs(int st,int fa = -1){ for(vector<pair<int,int> >::iterator it = edge[st].begin(); it != edge[st].end();it++){ pair<int,int> x = *it; if(x.first == fa) continue; dfs(x.first,st); ans += dp[st] * siz[x.first] + (dp[x.first] + siz[x.first] * x.second) * siz[st]; dp[st] += dp[x.first] + siz[x.first] * x.second; siz[st] += siz[x.first]; }}int main(){ scanf("%s",arr); int len = strlen(arr); reverse(arr,arr+len); SAM.build(arr); SAM.treeBuild(); ans = 0; dfs(SAM.root); printf("%lld\n",ans); return 0;}
0 0
- 【BZOJ 3238】 [Ahoi2013]差异
- bzoj-3238 差异
- bzoj 3238: [Ahoi2013]差异
- bzoj 3238 差异
- bzoj 3238 差异
- BZOJ 3238 [Ahoi2013]差异
- bzoj 3238 [Ahoi2013]差异
- BZOJ 3238 差异
- [BZOJ 3238][AHOI 2013]差异
- BZOJ 3238 差异 [后缀自动机]
- BZOJ 3238 AHOI2013 差异 后缀自动机
- BZOJ 3238 AHOI 2013 差异 后缀树
- bzoj 3238: [Ahoi2013]差异 后缀数组
- BZOJ 3238: [Ahoi2013]差异 后缀数组
- 后缀自动机+DP BZOJ 3238 差异
- bzoj 3238: [Ahoi2013]差异 后缀自动机
- bzoj 3238: [Ahoi2013]差异 后缀树
- bzoj 3238 ahoi2013差异 后缀数组
- Android实现简单计算器
- UI层自动化测试框架(四):对象库层
- POJ 2373 Dividing the Path(队列dp)
- Egret开发HTML5小游戏代码分享
- 飞机游戏:屏幕滚动,飞机拖拽,边界设置,子弹跟随
- bzoj 3238 差异
- Source Insight---自定义宏
- BZOJ 1269 splay
- 字符串的分隔方法 split()
- 博客转移到 http://blog.sxin.me
- curse下面的键盘模式输入
- 9.7总结
- 代码的规范性
- Permutations