bzoj3238后缀自动机-线性构造后缀树
来源:互联网 发布:淘宝酒水保证金 编辑:程序博客网 时间:2024/05/17 23:51
不懂线性构造后缀树的看这里:http://blog.csdn.net/guoshiyuan484/article/details/73658551
这个题主要就是注意他计算的是后缀,所以我们让后缀自动机主干上的点的size=1因为不管你怎么构造后缀自动机,在从原点一直连续转移到结尾点的路径上,每个点的最长串一定都是一个后缀(当然我说的是让原来的字符串反转后构造出来的自动机!)
其他就是dp的时候有一些技巧注意,具体看代码,哦还有注意用long long
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<string.h>using namespace std;struct treee{ int fa,nextt[29]; long long max,size;};treee tree[2000000];vector<int>to[2000000];int tot = 2;char s[600000];void construct(char *s,int len){ int last = 1; tree[1].max = 0; for (int i = len-1; i>=0; i--) { int temp = s[i] - 'a'; int now = tot; tree[now].max = tree[last].max + 1; tree[tot].size = 1; int tempfa = last; last = now; while (tempfa&&tree[tempfa].nextt[temp] == 0)tree[tempfa].nextt[temp] = now,tempfa=tree[tempfa].fa; if (!tempfa) { tree[now].fa = 1; } else { int link = tree[tempfa].nextt[temp]; if (tree[link].max == tree[tempfa].max + 1)tree[now].fa = link; else { int neww = ++tot; tree[neww] = tree[link]; tree[neww].size = 0; tree[neww].max = tree[tempfa].max + 1; tree[now].fa = neww; tree[link].fa = neww; while (tempfa&&tree[tempfa].nextt[temp] == link)tree[tempfa].nextt[temp] = neww, tempfa = tree[tempfa].fa;//由于头结点是空的,所以对于这道题而言该不该都是无所谓的。 } } tot++; } for (int i = tot - 1; i > 1; i--)to[tree[i].fa].push_back(i);}long long dfs(int num,long long &ans){ for (int i = 0; i < to[num].size(); i++) { int kk = to[num][i]; tree[num].size += dfs(kk, ans); } ans += tree[num].size*(tree[num].size - 1)*(tree[num].max-tree[tree[num].fa].max); return tree[num].size;}int main(){ scanf("%s", s); long long n = strlen(s); long long ans=0; //long long n = 500000; construct(s, n); dfs(1, ans); long long all = n*(n - 1)*(n + 1) / 2; all -= ans; printf("%lld\n",all); return 0;}
为了好复制:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;
struct treee
{
int fa,nextt[29];
long long max,size;
};
treee tree[2000000];
vector<int>to[2000000];
int tot = 2;
char s[600000];
void construct(char *s,int len)
{
int last = 1; tree[1].max = 0;
for (int i = len-1; i>=0; i--)
{
int temp = s[i] - 'a'; int now = tot;
tree[now].max = tree[last].max + 1; tree[tot].size = 1; int tempfa = last; last = now;
while (tempfa&&tree[tempfa].nextt[temp] == 0)tree[tempfa].nextt[temp] = now,tempfa=tree[tempfa].fa;
if (!tempfa)
{
tree[now].fa = 1;
}
else
{
int link = tree[tempfa].nextt[temp];
if (tree[link].max == tree[tempfa].max + 1)tree[now].fa = link;
else
{
int neww = ++tot; tree[neww] = tree[link]; tree[neww].size = 0; tree[neww].max = tree[tempfa].max + 1;
tree[now].fa = neww; tree[link].fa = neww;
while (tempfa&&tree[tempfa].nextt[temp] == link)tree[tempfa].nextt[temp] = neww, tempfa = tree[tempfa].fa;//由于头结点是空的,所以对于这道题而言该不该都是无所谓的。
}
}
tot++;
}
for (int i = tot - 1; i > 1; i--)to[tree[i].fa].push_back(i);
}
long long dfs(int num,long long &ans)
{
for (int i = 0; i < to[num].size(); i++)
{
int kk = to[num][i];
tree[num].size += dfs(kk, ans);
}
ans += tree[num].size*(tree[num].size - 1)*(tree[num].max-tree[tree[num].fa].max);
return tree[num].size;
}
int main()
{
scanf("%s", s);
long long n = strlen(s);
long long ans=0;
//long long n = 500000;
construct(s, n);
dfs(1, ans);
long long all = n*(n - 1)*(n + 1) / 2;
all -= ans;
printf("%lld\n",all);
return 0;
}
- bzoj3238后缀自动机-线性构造后缀树
- 后缀自动机与线性构造后缀树
- 【bzoj3238】差异 后缀自动机
- bzoj3238 [ AHOI2013 ] --后缀自动机
- 【BZOJ3238】【Ahoi2013】差异 后缀自动机
- [BZOJ3238] [AHOI2013] 差异 - 后缀自动机
- bzoj3238 [Ahoi2013]差异 后缀自动机
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- [BZOJ3238][Ahoi2013]差异(后缀自动机||后缀数组)
- 后缀树线性构造算法
- 后缀自动机的构造
- 后缀自动机的构造
- 【后缀自动机】自动机<->后缀树<->后缀数组
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- 【BZOJ 3238】[Ahoi2013]差异 后缀自动机构造后缀树
- 【BZOJ3238】差异 后缀数组
- 后缀树与后缀自动机
- 后缀自动机构造过程演示
- [leetcode]381. Insert Delete GetRandom O(1)
- LOI队内题单qwq
- 重装win10系统
- 检查文件类型
- Spring Cloud Feign 使用方式
- bzoj3238后缀自动机-线性构造后缀树
- UVA
- 组合数奇偶性判定方式
- 链表基本操作
- 关于C++ const 的全面总结
- 51Nod 1082与7无关的数(打表)
- 机器学习方法篇(10)------随机森林
- 关于float转int的函数实现
- Java基础之初识Java