• bzoj 3238差异


    3238: [Ahoi2013]差异

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 1420  Solved: 662
    [Submit][Status][Discuss]

    Description

    Input

    一行,一个字符串S

    Output

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

    Sample Input

    cacao

    Sample Output


    54

    HINT



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

     
    题解:
    right集合:pnt树上的子树sz大小(不统计nq节点)
    把串倒过来建后缀自动机,两个状态的lcp是pnt树上lca的val,也是串中两个前缀的最长公共后缀,即为原串的最长公共前缀。
    一个点的所有儿子的每个出现位置两两的lcp均为这个点的val,剩下的是减去子树内lcp更长的串的贡献。注意减去的应该是sz[i]*sz[i - 1],而不是子树去重后的答案
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define maxn 1000020
     6 
     7 typedef long long LL;
     8 struct node{
     9     int next[27],val,pnt;
    10 }sam[maxn];
    11 int a[maxn],num[maxn],sz[maxn];
    12 int n,m,root,tot,last;
    13 LL ans,f[maxn],g[maxn];
    14 char ch[maxn];
    15 
    16 inline void add(int x){
    17     int np = ++tot,p = last;
    18     sam[np].val = sam[p].val + 1;
    19     sz[np] = 1;
    20     while ( p && !sam[p].next[x] ) sam[p].next[x] = np , p = sam[p].pnt;
    21     int q = sam[p].next[x];
    22     if ( !q ) sam[p].next[x] = np , sam[np].pnt = p;
    23     else if ( q && sam[p].val + 1 == sam[q].val ) sam[np].pnt = q;
    24     else{
    25         int nq = ++tot;
    26         sam[nq].val = sam[p].val + 1;
    27         sam[nq].pnt = sam[q].pnt;
    28         sam[q].pnt = sam[np].pnt = nq;
    29         memcpy(sam[nq].next,sam[q].next,sizeof(sam[q].next));
    30         while ( p && sam[p].next[x] == q ) sam[p].next[x] = nq , p = sam[p].pnt;
    31         if ( sam[p].next[x] == q ) sam[p].next[x] = nq;
    32     }
    33     last = np;
    34 }
    35 inline void getsort(){
    36     for (int i = 1 ; i <= tot ; i++) num[sam[i].val]++;
    37     for (int i = 1 ; i <= n ; i++) num[i] += num[i - 1];
    38     for (int i = 1 ; i <= tot ; i++) a[num[sam[i].val]--] = i;
    39     for (int i = tot ; i >= 1 ; i--) {
    40         sz[sam[a[i]].pnt] += sz[a[i]];
    41            f[a[i]] += (LL)sz[a[i]] * (sz[a[i]] - 1);
    42         f[sam[a[i]].pnt] -= (LL)sz[a[i]] * (sz[a[i]] - 1);
    43     }
    44 }
    45 int main(){
    46     scanf("%s",ch + 1);
    47     n = strlen(ch + 1);
    48     for (int i = n ; i >= 1 ; i--){
    49         add(ch[i] - 'a');
    50     }
    51     getsort();
    52     ans = (LL)(n + 1) * n * (n - 1) >> 1;
    53     for (int i = 1 ; i <= tot ; i++) ans -= f[i] * (LL)sam[i].val;
    54     printf("%lld
    ",ans);
    55     return 0;
    56 }
    View Code
     
  • 相关阅读:
    边框的作用之产生相对margin
    css3 实现切换显示隐藏效果
    Vue 获取数据、事件对象、todolist
    Vue 双向数据绑定、事件介绍以及ref获取dom节点
    Vue 目录结构分析 数据绑定 绑定属性 循环渲染数据 数据渲染
    Vue 安装环境创建项目
    进程&线程
    生成Excel
    JQuery input file 上传图片
    0908期 HTML 样式表属性
  • 原文地址:https://www.cnblogs.com/zqq123/p/5282793.html
Copyright © 2020-2023  润新知