zoukankan      html  css  js  c++  java
  • 【BZOJ 3238】 3238: [Ahoi2013]差异(SAM)

    3238: [Ahoi2013]差异

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 3047  Solved: 1375

    Description

    Input

    一行,一个字符串S

    Output

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

    Sample Input

    cacao

    Sample Output


    54

    HINT



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

    Source

    【分析】

      这题先把sigma len 加上。

      然后考虑一下减掉的是什么。

      对于每个子串,假设出现次数是x,那么对答案的贡献就是x*(x-1)/2*2即ans-=x*(x-1)。

      这个用SAM对每个点的right进行计算即可。

      当然也可以用后缀数组。【后缀数组要用单调栈吧?套路啊。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 500010
     8 #define LL long long
     9 
    10 struct node
    11 {
    12     int son[30],pre,step,rt;
    13     // node() {rt=0;}
    14 }t[Maxn*2];
    15 int v[Maxn*2],q[Maxn*2];
    16 
    17 struct sam
    18 {
    19     int last,tot;
    20     void extend(int k)
    21     {
    22         int np=++tot,p=last;
    23         t[np].step=t[p].step+1;
    24         t[np].rt=1;
    25         while(p&&!t[p].son[k])
    26         {
    27             t[p].son[k]=np;
    28             p=t[p].pre;
    29         }
    30         if(!p) t[np].pre=1;
    31         else
    32         {
    33             int q=t[p].son[k];
    34             if(t[q].step==t[p].step+1) t[np].pre=q;
    35             else
    36             {
    37                 int nq=++tot;
    38                 memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
    39                 t[nq].step=t[p].step+1;
    40                 t[nq].pre=t[q].pre;
    41                 t[q].pre=t[np].pre=nq;
    42                 while(p&&t[p].son[k]==q)
    43                 {
    44                     t[p].son[k]=nq;
    45                     p=t[p].pre;
    46                 }
    47             }
    48         }
    49         last=np;
    50     }
    51     void init()
    52     {
    53         memset(v,0,sizeof(v));
    54         for(int i=1;i<=tot;i++) v[t[i].step]++;
    55         for(int i=1;i<=tot;i++) v[i]+=v[i-1];
    56         for(int i=tot;i>=1;i--) q[v[t[i].step]--]=i;
    57         
    58         for(int i=tot;i>=1;i--)
    59         {
    60             int nw=q[i];
    61             t[t[nw].pre].rt+=t[nw].rt;
    62         }
    63     }
    64 }sam;
    65 
    66 char s[Maxn];
    67 
    68 int main()
    69 {
    70     LL ans=0;
    71     scanf("%s",s);
    72     int l=strlen(s);
    73     sam.last=sam.tot=1;
    74     for(int i=0;i<l;i++) sam.extend(s[i]-'a'+1);
    75     ans=1LL*l*(l+1)*(l-1)/2;
    76     sam.init();t[1].step=0;
    77     for(int i=2;i<=sam.tot;i++)
    78     {
    79         ans-=1LL*(t[i].step-t[t[i].pre].step)*t[i].rt*(t[i].rt-1);
    80     }
    81     printf("%lld
    ",ans);
    82     return 0;
    83 }
    View Code

    2017-04-17 21:06:17

  • 相关阅读:
    document基本操作 动态脚本-动态样式-创建表格
    js原型模式和继承
    NuGet本地包自定义路径
    技术文档链接收藏
    数据结构排序
    Insertion Sort
    选择排序之javascript
    冒泡排序之javascript
    C++双向链表
    单向链表
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6724886.html
Copyright © 2011-2022 走看看