zoukankan      html  css  js  c++  java
  • [ZJOI2015]诸神眷顾的幻想乡

    OJ题号:
    BZOJ3926、洛谷3346

    题目大意:
      给定一棵带权树,定义两个路径是不同的当且仅当两个路径上的权值构成的串不同,求本质不同的路径个数。

    思路:
      广义后缀自动机。
      从每个叶子结点开始DFS,并依次加入到SAM中,对于每个加入的结点,last状态是其父亲节点所在的状态,其余插入过程与普通SAM类似。
      每个叶子结点的last状态为root。
      询问过程与普通SAM完全相同。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<vector>
     4 #include<cstring>
     5 inline int getint() {
     6     char ch;
     7     while(!isdigit(ch=getchar()));
     8     int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int V=100001;
    13 std::vector<int> e[V];
    14 int deg[V];
    15 inline void add_edge(const int u,const int v) {
    16     e[u].push_back(v);
    17     deg[u]++;
    18 }
    19 int col[V];
    20 class GeneralSuffixAutomaton {
    21     private:
    22         static const int SIGMA_SIZE=10,MAX_STATE=V<<5;
    23         struct State {
    24             int link,go[SIGMA_SIZE],len;
    25         };
    26         State s[MAX_STATE];
    27         int sz,newState(const int l) {
    28             sz++;
    29             s[sz].len=l;
    30             return sz;
    31         }
    32         int extend(int p,const int w) {
    33             int new_p=newState(s[p].len+1);
    34             while(p&&!s[p].go[w]) {
    35                 s[p].go[w]=new_p;
    36                 p=s[p].link;
    37             }
    38             if(!p) {
    39                 s[new_p].link=root;
    40             } else {
    41                 int q=s[p].go[w];
    42                 if(s[q].len==s[p].len+1) {
    43                     s[new_p].link=q;
    44                 } else {
    45                     int new_q=newState(s[p].len+1);
    46                     memcpy(s[new_q].go,s[q].go,sizeof s[q].go);
    47                     s[new_q].link=s[q].link;
    48                     s[q].link=s[new_p].link=new_q;
    49                     while(p&&s[p].go[w]==q) {
    50                         s[p].go[w]=new_q;
    51                         p=s[p].link;
    52                     }
    53                 }
    54             }
    55             return new_p;
    56         }
    57     public:
    58         int root;
    59         GeneralSuffixAutomaton() {
    60             root=newState(0);
    61         }
    62         void build(const int x,const int par,const int lastptr) {
    63             int p=extend(lastptr,col[x]);
    64             for(unsigned i=0;i<e[x].size();i++) {
    65                 int &y=e[x][i];
    66                 if(y==par) continue;
    67                 build(y,x,p);
    68             }
    69         }
    70         long long query() {
    71             long long ret=0;
    72             for(int i=1;i<=sz;i++) {
    73                 if(s[i].link) {
    74                     ret+=s[i].len-s[s[i].link].len;
    75                 }
    76             }
    77             return ret;
    78         }
    79 };
    80 GeneralSuffixAutomaton sam;
    81 int main() {
    82     int n=getint(),m=getint();
    83     for(int i=1;i<=n;i++) col[i]=getint();
    84     for(int i=1;i<n;i++) {
    85         int u=getint(),v=getint();
    86         add_edge(u,v);
    87         add_edge(v,u);
    88     }
    89     for(int i=1;i<=n;i++) {
    90         if(deg[i]==1) {
    91             sam.build(i,0,sam.root);
    92         }
    93     }
    94     printf("%lld
    ",sam.query());
    95     return 0;
    96 }
  • 相关阅读:
    WORD数据类型数据类型及 Bit,Byte,WORD,DWORD区别和联系
    C++指针探讨 (三) 成员函数指针
    visual c++中常用MFC文件及库文件
    SVN版本管理软件的使用介绍与教程
    C++星号的含义
    ajaxValidator 常见问题解决(传参,中文乱码)
    C++中的常量
    孙鑫老师VC++深入详解第一节课源代码(这样写更好理解)
    C/C++ 头文件 常用头文件功能查询表
    C++指针探讨 (一)数据指针
  • 原文地址:https://www.cnblogs.com/skylee03/p/7521017.html
Copyright © 2011-2022 走看看