zoukankan      html  css  js  c++  java
  • BZOJ 3926 诸神眷顾的幻想乡

    BZOJ 3926 诸神眷顾的幻想乡

    开始看错题看成了每个点度数不超过20 后来翻了翻题解原来看错题的不止我一个

    既然叶子数量不超过20,考虑树上的任何一条路径,以任何点为根时,如果它不是一条从上到下的路径,那么以它的任意一端的子树内的某一个叶子为根必然可以变成从上到下的。否则,以它处于下端的点的子树内的叶子为根也可以做到。

    所以如果以每一个叶子为根的串建成个 Trie 并且把所有单词丢进广义SAM就做完了。

    说一下广义SAM的构建:

    • 最简单轻松的,如果只是插入一些字符串,那么插入一个后把 last 设置为根就好了。

      据说这种构造在某些时候是会死掉的但是好写啊,如果单词重复据说会加多点。。但是平时写由于很难出错一直写的这个。

    • 标准的,对于所有串构造一棵 Trie 然后 BFS 这个 Trie 来构造。加入一个点的时候就把 last 设置为它父亲加入完时的 last。

      注意,写 DFS 是会被卡的!可以看这篇博客

    空间开小WA了发海星

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include "queue"
    using namespace std;
    typedef long long ll;
    #define MAXN 2000006
    
    int n , lst , m;
    char ch[MAXN];
    
    struct SAM{
        int son[MAXN][11]; // sons
        int par[MAXN] , len[MAXN]; // node
        int cnt , ecnt;
        void init(  ) {
            memset( son , 0 , sizeof son );
            cnt = lst = 1; ecnt = 0;
        }
        void ins( int x ) {
            int cur = ++ cnt;
            len[cur] = len[lst] + 1;
            int p = lst;
            while( p && !son[p][x] ) son[p][x] = cur , p = par[p];
            if( !p ) par[cur] = 1;
            else {
                int q = son[p][x];
                if( len[q] == len[p] + 1 ) par[cur] = q;
                else {
                    int cl = ++ cnt;
                    memcpy( son[cl] , son[q] , sizeof son[q] );
                    par[cl] = par[q]; // copy
                    len[cl] = len[p] + 1 , par[q] = par[cur] = cl;
                    for( ; son[p][x] == q ; p = par[p] ) son[p][x] = cl;
                }
            }
            lst = cur;
        }
        int ch[MAXN][10] , pos[MAXN];
        void build(  ) {
            init( );
            queue<int> Q;
            Q.push( 0 ); pos[0] = 1;
            while( !Q.empty() ) {
                int u = Q.front(); Q.pop();
                for( int i = 0 ; i < 10 ; ++ i ) if( ch[u][i] ) {
                    Q.push( ch[u][i] );
                    lst = pos[u]; ins( i ); pos[ch[u][i]] = lst;
                }
            }
        }
        long long work( ) {
            long long res = 0;
            for( int i = 2 ; i <= cnt ; ++ i ) {
                res += len[i] - len[par[i]];
            }
            return res;
        }
    } S ;
    namespace wtf {
    
        int n , m;
    
        int head[MAXN] , to[MAXN << 1] , nex[MAXN << 1] , ecn;
        void ade( int u , int v ) {
            to[++ ecn] = v , nex[ecn] = head[u] , head[u] = ecn;
        }
    
        int w[MAXN] , cn;
    
        void build( int u , int ps , int fa ) {
            for( int i = head[u] ; i ; i = nex[i] ) {
                int v = to[i];
                if( v == fa ) continue;
                int& x = S.ch[ps][w[v]];
                if( !x ) x = ++ cn;
                build( v , x , u );
            }
        }
        int c;
        void main() {
            cin >> n >> c;
            for( int i = 1 ; i <= n ; ++ i )
                scanf("%d",&w[i]);
            for( int i = 1 , u , v ; i < n ; ++ i )
                scanf("%d%d",&u,&v) , ade( u , v ) , ade( v , u );
            S.init();
            for( int i = 1 ; i <= n ; ++ i )
                if( !nex[head[i]] ) build( i , S.ch[0][w[i]] ? S.ch[0][w[i]] : ( S.ch[0][w[i]] = ++ cn ) , i );
            S.build();
            cout << S.work( ) << endl;
        }
    }
    int main() {
        wtf::main();
    }
    
  • 相关阅读:
    Enables DNS lookups on client IP addresses 域名的分层结构
    移除 URL 中的 index.php
    Design and Architectural Goals
    The Model represents your data structures.
    If a cache file exists, it is sent directly to the browser, bypassing the normal system execution.
    UNION WHERE
    cookie less
    http 2
    UNION DISTINCT
    联合约束 CONCAT()
  • 原文地址:https://www.cnblogs.com/yijan/p/bzoj3926.html
Copyright © 2011-2022 走看看