zoukankan      html  css  js  c++  java
  • Codeforces 1207 G. Indie Album

    Codeforces 1207 G. Indie Album

    解题思路

    离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 (len[u] = len[fa]) 的节点,需要特殊处理,所以写一个博客来贴板子,之前用Awd博客上的那个好像不太能处理干净。

    code

    
    /*program by mangoyang*/
    #include <bits/stdc++.h>
    #define inf ((ll) 1e18)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
    	int ch = 0, f = 0; x = 0;
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	if(f) x = -x;
    }
     
    const int N = 1600005;
     
    vector<int> g[N], d[N], rt;
    vector<pair<int, int> > q[N];
    string str[N];
    char strr[N];
    int ans[N], n, m;
     
    namespace Bit{
        int s[N];
        inline void modify(int x, int y){
            for(int i = x; i < N; i += i & -i) s[i] += y;
        }
        inline int query(int l, int r){
            int res = 0;
            for(int i = l - 1; i; i -= i & -i) res -= s[i];
            for(int i = r; i; i -= i & -i) res += s[i];
            return res;
        }
    }
    namespace SAM{
        vector<int> g[N];
        int ch[N][26], dfn[N], len[N], fa[N], sz[N], size = 1, tail = 1, cnt;
        inline int newnode(int x){ return len[++size] = x, size; }
        inline void ins(int c, int pos){
            int p = tail;
            if(ch[p][c]){
                if(ch[p][c] && len[ch[p][c]] == len[p] + 1){
                    int np = ch[p][c];
                    if(pos <= n) d[pos].push_back(np);
                    return (void) (tail = np);
                }
                int np = newnode(len[p] + 1), q = ch[p][c];
                if(pos <= n) d[pos].push_back(np);
                fa[np] = fa[q], fa[q] = np;
                for(int i = 0; i < 26; i++) ch[np][i] = ch[q][i];
                for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = np;
                return (void) (tail = np);
            }
            int np = newnode(len[p] + 1);
            if(pos <= n) d[pos].push_back(np);
            for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
            if(!p) return (void) (fa[np] = 1, tail = np);
            int q = ch[p][c];
            if(len[q] == len[p] + 1) fa[np] = q;
            else{
                int nq = newnode(len[p] + 1);
                fa[nq] = fa[q], fa[q] = fa[np] = nq;
                for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
                for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
            } tail = np;
        }
        inline void addedge(){
            for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
        }
        inline void dfs(int u){
            dfn[u] = ++cnt, sz[u] = 1;
            for(int i = 0; i < (int) g[u].size(); i++)
                dfs(g[u][i]), sz[u] += sz[g[u][i]];
        }
    }
    inline void build(int u){
        int tmp = SAM::tail;
        for(int i = 0; i < (int) str[u].size(); i++)
            SAM::ins(str[u][i] - 'a', u);
        for(int i = 0; i < (int) g[u].size(); i++)
            build(g[u][i]);
        SAM::tail = tmp;
    }
    inline void solve(int u){
        for(int i = 0; i < (int) d[u].size(); i++)
            Bit::modify(SAM::dfn[d[u][i]], 1); 
        for(int i = 0; i < (int) q[u].size(); i++){
            int x = q[u][i].first, y = q[u][i].second;
            ans[x] = Bit::query(SAM::dfn[y], SAM::dfn[y] + SAM::sz[y] - 1);
        } 
        for(int i = 0; i < (int) g[u].size(); i++)        
            solve(g[u][i]);
        for(int i = 0; i < (int) d[u].size(); i++)
            Bit::modify(SAM::dfn[d[u][i]], -1);
    }
    int main(){
        read(n);
        for(int i = 1, x, y; i <= n; i++){
            read(x);
            if(x == 1) 
                cin >> str[i], rt.push_back(i);
            else 
                read(y), cin >> str[i], g[y].push_back(i);
        }
        for(int i = 0; i < (int) rt.size(); i++) 
            build(rt[i]);
        read(m);
        for(int i = 1, x; i <= m; i++){
            read(x), scanf("%s", strr); 
            int lenth = strlen(strr);
            for(int j = 0; j < lenth; j++)
                SAM::ins(strr[j] - 'a', n + 1);
            q[x].push_back(make_pair(i, SAM::tail));
            SAM::tail = 1;
        }
        SAM::addedge(), SAM::dfs(1);
        for(int i = 0; i < (int) rt.size(); i++)
            solve(rt[i]);
        for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
        return 0;
    }
    
    
  • 相关阅读:
    算法------------数组----------------两个数组的交集 II
    算法-----------数组------------只出现一次的数字
    算法------数组---------存在重复元素
    androd hook acitivity 启动流程,替换启动的activity(Android Instrumentation)
    算法--------旋转数组
    Android 项目,没有可运行的Module项
    Java多线程系列目录(共43篇)
    python3:tuple元组
    python 3 :list
    python3 基本数据类型
  • 原文地址:https://www.cnblogs.com/mangoyang/p/11455519.html
Copyright © 2011-2022 走看看