zoukankan      html  css  js  c++  java
  • LG P3966 [TJOI2013]单词

    Description

    小张最近在忙毕设,所以一直在读论文。一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次。

    Solution

    对这些单词建出AC自动机,可能会有重复的单词,记录每一个单词第一次出现是第几个

    在AC自动机上匹配时,匹配串经过的所有点打标记,每个点对其fail指向的点做贡献,跑一边DFS求子树和

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int n,tot=1,mp[205],len,len2,siz[1000005],pos[205];
    char s[1000005],t[1000205];
    struct ACAM{
        int ch[26],fa,tag;
    }tr[1000005];
    vector<int>ve[1000005];
    queue<int>q;
    inline int read(){
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return f*w;
    }
    void insert(char *s,int id){
        int u=1;
        for(int i=1;i<=len;i++){
            if(!tr[u].ch[s[i]-'a'])tr[u].ch[s[i]-'a']=++tot;
            u=tr[u].ch[s[i]-'a'];
        }
        if(!tr[u].tag)mp[id]=tr[u].tag=id,pos[id]=u;
        else mp[id]=tr[u].tag;
    }
    void BFS(){
        for(int i=0;i<26;i++)tr[0].ch[i]=1;
        q.push(1);
        while(q.size()){
            int u=q.front();
            q.pop();
            for(int i=0;i<26;i++){
                int v=tr[u].ch[i],f=tr[u].fa;
                if(!v){tr[u].ch[i]=tr[f].ch[i];continue;}
                tr[v].fa=tr[f].ch[i],q.push(v);
            }
        }
    }
    void ask(char *s){
        int u=1;
        for(int i=1;i<=len2;i++){
            if(t[i]=='$'){u=1;continue;}
            u=tr[u].ch[t[i]-'a'],++siz[u];
        }
    }
    void dfs(int k){
        for(int i=0;i<ve[k].size();i++){
            int v=ve[k][i];
            dfs(v),siz[k]+=siz[v];
        }
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++){
            scanf("%s",s+1),len=strlen(s+1),insert(s,i);
            for(int i=1;i<=len;i++)t[++len2]=s[i];
            t[++len2]='$';
        }
        BFS();
        for(int i=2;i<=tot;i++)ve[tr[i].fa].push_back(i);
        ask(t+1),dfs(1);
        for(int i=1;i<=n;i++)printf("%d
    ",siz[pos[mp[i]]]);
        return 0;
    }
    [TJOI2013]单词
  • 相关阅读:
    剑指 Offer 51. 数组中的逆序对
    剑指 Offer 68
    剑指 Offer 68
    JS绑定事件三种方式
    图片懒加载原理及实现
    资源加载过程
    了解JS单线程和任务队列!
    JS函数作用域提升
    JS函数种类详解
    ES6之模版字符串
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14629807.html
Copyright © 2011-2022 走看看