[bzoj3238][Ahoi2013]差异——后缀自动机
Brief Description

Algorithm Design
下面给出后缀自动机的一个性质:
两个子串的最长公共后缀,位于这两个串对应的状态在parent树上的lca状态上。并且最长公共后缀的长度就是lca状态的len。
证明:对于一个串,他的所有祖先节点都是他的后缀,并且深度越大,长度越长,由此不难说明两个子串的最长公共后缀一定在lca状态上。考察这个lca,他代表的所有子串一定都是两个子串的公共后缀,我们直接取最大的就可以了。
有了这个性质,我们就可以开始乱搞了。
Code
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
const ll maxn = 500100 << 1;
char s[maxn], str[maxn];
ll head[maxn], f[maxn];
ll ans;
ll n, cnt = 1;
struct edge {
ll to, next;
} e[maxn];
void add_edge(ll u, ll v) {
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
struct Suffix_Automaton {
ll fa[maxn], trans[maxn][26], len[maxn], right[maxn];
ll last, root, sz;
bool flag[maxn];
void init() {
memset(flag, 0, sizeof(flag));
sz = 0;
last = root = ++sz;
}
void insert(ll x) {
ll p = last, np = last = ++sz;
len[np] = len[p] + 1;
flag[np] = 1;
right[np] = right[p] + 1;
for (; !trans[p][x]; p = fa[p])
trans[p][x] = np;
if (p == 0)
fa[np] = root;
else {
ll q = trans[p][x];
if (len[q] == len[p] + 1) {
fa[np] = q;
} else {
ll nq = ++sz;
fa[nq] = fa[q];
memcpy(trans[nq], trans[q], sizeof(trans[q]));
len[nq] = len[p] + 1;
fa[q] = fa[np] = nq;
for (; trans[p][x] == q; p = fa[p])
trans[p][x] = nq;
}
}
}
void pre() {
for (ll i = 1; i <= sz; i++) {
if (fa[i])
add_edge(fa[i], i);
}
}
void print() {
for (ll i = 1; i <= sz; i++) {
printf("%3lld ", i);
}
printf("\n");
for (ll i = 1; i <= sz; i++) {
printf("%3lld ", len[i]);
}
printf("\n");
for (ll i = 1; i <= sz; i++)
if (flag[i]) {
printf("%lld:", i);
for (ll j = 1; j <= len[i]; j++)
printf("%c", str[right[i] - (len[i] - j + 1) + 1]);
printf("\n");
}
printf("\n");
}
} sam;
void dfs(ll x) {
ll ct = 0;
f[x] = sam.flag[x] ? 1 : 0;
for (ll i = head[x]; i; i = e[i].next) {
dfs(e[i].to);
ans -= 1ll * 2 * (1ll * f[e[i].to] * ct) * (sam.len[x]);
ct += f[e[i].to];
}
if (f[x] == 1) {
ans -= 1ll * 2 * (1ll * ct) * (sam.len[x]);
}
f[x] += ct;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%s", s + 1);
n = strlen(s + 1);
sam.init();
for (ll i = 1; i <= n; i++) {
ans += (n * i) - i * i + ((n * n - i * i + n - i) >> 1);
str[i] = s[n - i + 1];
}
for (ll i = 1; i <= n; i++)
sam.insert(str[i] - 'a');
sam.pre();
// sam.print();
// printf("%lld\n", ans);
dfs(sam.root);
printf("%lld\n", ans);
}
[bzoj3238][Ahoi2013]差异——后缀自动机的更多相关文章
- BZOJ3238: [Ahoi2013]差异(后缀自动机)
题意 题目链接 Sol 前面的可以直接算 然后原串翻转过来,这时候变成了求任意两个前缀的最长公共后缀,显然这个值应该是\(len[lca]\),求出\(siz\)乱搞一下 #include<bi ...
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2512 Solved: 1140[Submit][Status ...
- bzoj3238 [Ahoi2013]差异 后缀数组+单调栈
[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- [Ahoi2013]差异(后缀自动机)
/* 前面的那一坨是可以O1计算的 后面那个显然后缀数组单调栈比较好写??? 两个后缀的lcp长度相当于他们在后缀树上的lca的深度 那么我们就能够反向用后缀自动机构造出后缀树然后统计每个点作为lca ...
- 洛谷P4248 [AHOI2013]差异(后缀自动机求lcp之和)
题目见此 题解:首先所有后缀都在最后一个np节点,然后他们都是从1号点出发沿一些字符边到达这个点的,所以下文称1号点为根节点,我们思考一下什么时候会产生lcp,显然是当他们从根节点开始一直跳相同节点的 ...
- BZOJ 3238 [Ahoi2013]差异 ——后缀自动机
后缀自动机的parent树就是反串的后缀树. 所以只需要反向构建出后缀树,就可以乱搞了. #include <cstdio> #include <cstring> #inclu ...
- [AHOI2013]差异 后缀自动机_Parent树
题中要求: $\sum_{1\leqslant i < j \leq n } Len(T_{i}) +Len(T_{j})-2LCP(T_{i},T_{j})$ 公式左边的部分很好求,是一个常量 ...
- BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP/后缀数组 单调栈)
题目链接 \(Description\) \(Solution\) len(Ti)+len(Tj)可以直接算出来,每个小于n的长度会被计算n-1次. \[\sum_{i=1}^n\sum_{j=i+1 ...
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...
随机推荐
- Android开发免费类库和工具集合
用于Android开发的免费类库和工具集合,按目录分类. Action Bars ActionBarSherlock Extended ActionBar FadingActionBar GlassA ...
- 27、理解js的继承机制(转载自阮一峰)
Javascript继承机制的设计思想 作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...
- FJWC 2019 游记
FJWC 2019 游记 Day 0 春节旅游, 刚从杭州绍兴一带赶回来, 然而并没有直接飞去福州, 去了厦门再去福州, 浪费了好多时间. Day 1 酒店到学校有 \(20\) 分钟的步行路程, 感 ...
- 『Golang』MongoDB在Golang中的使用(mgo包)
有关在Golang中使用mho进行MongoDB操作的最简单的例子.
- Qt 隐藏标题栏可移动升级版
在最出的时候,在Qt程序隐藏标题栏的情况下,实现界面可拖拽移动,是鼠标在在程序界面的任意位置都可以,现在这个版本是需要鼠标在程序界面的特定位置开可以 上代码 static QPoint last(0, ...
- Vm Ubuntu 文件共享问题
其实也是差不多的,就是需要重新安装一次工具 ,自己安装有问题,自己在手动安装一次就好了 下面是一个我的参考文章 http://blog.csdn.net/zz962/article/details/7 ...
- ubuntu12.04停留在grub界面问题
修改ubuntu 12.04 停留在grub界面的步骤: 1. 在/etc/default/grub配置文件中, 添加一项GRUB_RECORDFAIL_TIMEOUT: GRUB_TIMEOUT=2 ...
- [Binary Search] Leetcode 35, 74
35. Search Insert Position Description Given a sorted array and a target value, return the index if ...
- 用tensorflow实现自然语言处理——基于循环神经网络的神经语言模型
自然语言处理和图像处理不同,作为人类抽象出来的高级表达形式,它和图像.声音不同,图像和声音十分直觉,比如图像的像素的颜色表达可以直接量化成数字输入到神经网络中,当然如果是经过压缩的格式jpeg等必须还 ...
- 浅析Python中的main函数
Python作为一门较为灵活的解释型脚本语言,其中定义的main()函数只有当该Python脚本直接作为执行程序时才会执行: 当该python脚本被作为模块(module)引入(import)时,其中 ...