• BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp


    http://www.lydsy.com/JudgeOnline/problem.php?id=3238

    就算是全局变量,也不要忘记,初始化(吐血)。

    长得一副lca样,没想到是个树形dp(小丫头还有两幅面孔呢)。

    看代码实现吧,不大容易口头解释,把加的和减的分开算就可以了,减去的通过倒着建sam(相当于建一棵后缀树),然后算每个len取的次数实现,注意树归中一些避免重复操作。

     1 /**************************************************************
     2     Problem: 3238
     3     User: 137shoebills
     4     Language: C++
     5     Result: Accepted
     6     Time:3816 ms
     7     Memory:130688 kb
     8 ****************************************************************/
     9  
    10 #include<iostream>
    11 #include<cstdio>
    12 #include<algorithm>
    13 #include<cstring>
    14 #include<cmath>
    15 #include<map>
    16 using namespace std;
    17 const int maxn=500010;
    18 char ch1[maxn]={};
    19 int siz;
    20 struct nod{
    21     int sig[26];
    22     int f,len;
    23 }t[maxn*2];int tot=1,la=1;
    24 void add(int z){
    25     int x=++tot;int i=la;
    26     t[x].len=t[la].len+1;
    27     for(;i&&!t[i].sig[z];i=t[i].f)
    28         t[i].sig[z]=x;
    29     if(!i)t[x].f=1;
    30     else{
    31         int p=t[i].sig[z];
    32         if(t[p].len==t[i].len+1)t[x].f=p;
    33         else{
    34             int y=++tot;
    35             t[y]=t[p];t[y].len=t[i].len+1;
    36             t[x].f=t[p].f=y;
    37             for(;i&&t[i].sig[z]==p;i=t[i].f)
    38                 t[i].sig[z]=y;
    39         }
    40     }
    41     la=x;
    42 }
    43 struct node{
    44     int y,next;
    45 }e[maxn*2];int cnt=0;
    46 int head[maxn*2]={};
    47 long long dp[maxn*2]={},sum=0;
    48 void init(int x,int y){e[++cnt].y=y;e[cnt].next=head[x];head[x]=cnt;}
    49 void dfs(int x){
    50     int y;
    51     long long num=dp[x]*dp[x];
    52     for(int i=head[x];i;i=e[i].next){
    53         y=e[i].y;
    54         dfs(y);dp[x]+=dp[y];
    55         num+=dp[y]*dp[y];
    56     }
    57     sum+=(dp[x]*dp[x]-num)*t[x].len;
    58 }
    59 long long solve(){
    60     int j=1;
    61     for(int i=siz;i>=1;i--){
    62         j=t[j].sig[ch1[i]-'a'];
    63         dp[j]++;
    64     }
    65     for(int i=2;i<=tot;i++)
    66         init(t[i].f,i);
    67     dfs(1);
    68     return sum;
    69 }
    70 int main(){
    71     memset(t,0,sizeof(t));
    72     scanf("%s",ch1+1);siz=strlen(ch1+1);
    73     for(int i=siz;i>=1;i--)add((int)(ch1[i]-'a'));
    74     long long ans=0;
    75     for(int i=1;i<=siz;i++)ans+=(long long)i*(siz-1);
    76     printf("%lld
    ",ans-solve());
    77     return 0;
    78 }
    View Code

  • 相关阅读:
    HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)
    HDU 1241 Oil Deposits DFS(深度优先搜索) 和 BFS(广度优先搜索)
    邮件推广工具
    aix-syslog
    能量点
    知识picture
    C中运算符
    stdio.h头文件中申明的基本函数
    字符串
    指针字符串
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8570139.html
Copyright © 2020-2023  润新知