[BZOJ3238][Ahoi2013]差异

Posted Elder_Giang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3238][Ahoi2013]差异相关的知识,希望对你有一定的参考价值。

3238: [Ahoi2013]差异

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 3394  Solved: 1542
[Submit][Status][Discuss]

Description

技术分享

Input

一行,一个字符串S

Output

 

一行,一个整数,表示所求值

Sample Input

cacao

Sample Output


54

HINT

 



2<=N<=500000,S由小写英文字母组成

 

先把答案加的那部分弄出来,可以$O(1)$计算。。

然后剩下的部分可以通过建反串的后缀自动机,那么$Parent$树就是原串的后缀树。。

然后树形DP即可

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 500000 + 10;
struct State {
    int len, link, tot;
    int son[26];
}st[maxn * 2];
int cnt, last;
void sam_init() {
    cnt = last = 0;
    st[0].len = 0;
    st[0].link = -1;
    st[0].tot = 0;
    memset(st[0].son, 0, sizeof(st[0].son));
}
void sam_extend(char c) {
    int cur = ++cnt, idx = c - a;
    st[cur].len = st[last].len + 1;
    memset(st[cur].son, 0, sizeof(st[cur].son));
    st[cur].tot = 1;
    int p;
    for (p = last; p != -1 && !st[p].son[idx]; p = st[p].link)
        st[p].son[idx] = cur;
    if (p == -1) st[cur].link = 0;
    else {
        int q = st[p].son[idx];
        if (st[p].len + 1 == st[q].len) st[cur].link = q;
        else {
            int clone = ++cnt;
            st[clone].len = st[p].len + 1;
            memcpy(st[clone].son, st[q].son, sizeof(st[q].son));
            st[clone].link = st[q].link;
            st[clone].tot = 0;
            for (; p != -1 && st[p].son[idx] == q; p = st[p].link)
                st[p].son[idx] = clone;
            st[q].link = st[cur].link = clone;
        }
    }
    last = cur;
}
char S[maxn];
int len;
struct Edge {
    int to, next;
    Edge() {}
    Edge(int _t, int _n) : to(_t), next(_n) {}
}e[maxn * 2];
int fir[maxn * 2] = { 0 }, ecnt = 0;
inline void add(int u, int v) {
    e[++ecnt] = Edge(v, fir[u]); fir[u] = ecnt;
}
void build() {
    for (int i = 1; i <= cnt; i++)
        add(st[i].link, i);
}
long long ans;
void dfs(int u) {
    for (int v, i = fir[u]; i; i = e[i].next) {
        v = e[i].to;
        dfs(v);
        ans -= 2LL * st[u].len * st[u].tot * st[v].tot;
        st[u].tot += st[v].tot;
    }
}
int main() {
    scanf("%s", S);
    sam_init();
    len = strlen(S);
    for (int i = 0; i < len; i++)
        sam_extend(S[len - i - 1]);
    build();
    ans = (long long)(len + 1) * len * (len - 1) / 2;
    dfs(0);
    printf("%lld\n", ans);
    return 0;
}

 








以上是关于[BZOJ3238][Ahoi2013]差异的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3238: [Ahoi2013]差异

bzoj 3238: [Ahoi2013]差异 -- 后缀数组

bzoj3238 [Ahoi2013]差异

bzoj3238 [Ahoi2013]差异 后缀数组+单调栈

bzoj 3238: [AHOI2013]差异

BZOJ_3238_[Ahoi2013]差异_后缀自动机