zoukankan      html  css  js  c++  java
  • bzoj3172 [Tjoi2013]单词

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3172

    【题解】

    考虑建出AC自动机,那么fail树上每个点的父亲为fail,父亲->儿子为后缀关系(父亲是儿子后缀)

    那么走到父亲肯定走到了儿子,直接统计即可。

    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1.6e6 + 10;
    const int mod = 1e9+7;
    
    int n; char t[M];
    int v[M], ps[M]; vector<int> G[M];
    struct ACM {
        int ch[M][26], fail[M], siz, isend[M];
        inline void set() {siz = 0;}
        inline int ins(char *t) {
            int p = 0;
            for (int i=0; t[i]; ++i) {
                int c = t[i] - 'a';
                if(!ch[p][c]) ch[p][c] = ++siz;
                p = ch[p][c];
                v[p] ++;
            }
            return p;
        }
        queue<int> q;
        inline void build() {
            while(!q.empty()) q.pop();
            for (int c=0; c<26; ++c) {
                int p = ch[0][c];
                if(p) {
                    fail[p] = 0;
                    q.push(p);
                }
            }
            while(!q.empty()) {
                int top = q.front(); q.pop();
                for (int c=0; c<26; ++c) {
                    int p = ch[top][c];
                    if(!p) {
                        ch[top][c] = ch[fail[top]][c];
                        continue;
                    }
                    q.push(p);
                    int v = fail[top];
                    while(v && !ch[v][c]) v = fail[v];
                    fail[p] = ch[v][c];
                }
            }
        }
        inline void getfail() {
            for (int i=1; i<=siz; ++i) 
                G[fail[i]].push_back(i);
        }
    }S;
    
    inline void dfs(int x) {
        for (int i=0; i<G[x].size(); ++i) {
            int y = G[x][i];
            dfs(y);
            v[x] += v[y];
        }
    }
    
    int main() {
        cin >> n; S.set();
        for (int i=1; i<=n; ++i) {
            scanf("%s", t);
            ps[i] = S.ins(t);
        }
        S.build();
        S.getfail();
        dfs(0);
        for (int i=1; i<=n; ++i) printf("%d
    ", v[ps[i]]);
        return 0;
    }
    View Code
  • 相关阅读:
    day22 os模块
    开始 Dojo 开发
    Java 多线程编程
    Oracle 中常用数据字典大总结
    使用Java API的5个技巧
    Java 守护线程概述
    给Java新手的一些建议——Java知识点归纳(Java基础部分)
    消息中间件收录集
    2017年Java面试题整理
    Java 9 新特性快速预览
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3172.html
Copyright © 2011-2022 走看看