zoukankan      html  css  js  c++  java
  • UESTC1977-图书馆(AC自动机应用)

    M - 图书馆

    Time Limit: 2000 MS     Memory Limit: 256 MB
    Submit Status

    电子科技太学图书馆创建于1956年,馆舍总面积66974平方米,各类阅览室37个,阅览座位10023个(含在建新馆),馆藏总量371.8万册。

    为了更好地管理数量如此庞大的书籍,管理员准备对所有书籍进行一次统计、整理。图书管理员需要将相似的图书归为一类,为此它为每个分类选出了几个关键词,如果在一本书的文本中,关键词出现得越频繁,则说明这本书越有可能属于这一类。

    现在,管理员把这项重任交给你,并希望在太阳完全下山之前能够统计出每个关键词在书本中出现次数的总和。

    注:重复关键词重复统计。

    Input

    输入文件中第一行一个正整数 TT 表示测试数据组数。

    每组测试数据第一行为书籍内容,为长度不大于 1000000 的字符串 SS

    第二行为不多于 10000 的整数 NN ,表示关键词个数,接下去 NN 行,每行有长度不超过 50 的关键词字符串。

    数据保证字符串只由英文小写字母 a-z 组成,不存在空串。 T×|S|10000000T×|S|≤10000000

    Output

    每组测试数据输出一行,为每个关键词在书本中出现次数的总和。

    Sample input and output

    Sample InputSample Output
    1
    trumpet
    5
    trump
    drum
    pet
    rump
    rua
    3

    Hint

    trumpet 中出现了 trump pet rump 。  

    AC自动机模版题:

    #include<queue>  
    #include<cstdio>  
    #include<cstring>   
    #include<iostream>  
    #define MAXNODE 500005  
    using namespace std;  
    int n,T;  
    char str[1000005],s[100];  
    struct ACautomata  
    {  
        int ch[MAXNODE][26];  
        int f[MAXNODE];         // fail函数  
        int val[MAXNODE];       // 是否为单词结尾    
        int last[MAXNODE];      // 后缀链接   
        int cnt[10005];         // 每个单词出现次数   
        int tot;                // trie 单词总数   
        int num;                // 单词出现了几个   
        int time[10005];        //以val[i]结尾的单词数量


        void init()  
        {  
            num = 0;  
            tot = 1;  
            memset(ch[0],0,sizeof(ch[0]));  
            memset(cnt,0,sizeof(cnt));  
            memset(time,0,sizeof(time));  
        }  


        int idx(char c)             //获取编号
        {  
            return c - 'a';  
        }  


        void insert(char *s,int v)  //插入
        {  
            int u = 0,n = strlen(s);  
            for(int i = 0;i < n;i++)  
            {  
                int c = idx(s[i]);  
                if(!ch[u][c])  
                {  
                    memset(ch[tot],0,sizeof(ch[tot]));  
                    val[tot] = 0;  
                    ch[u][c] = tot++;   
                }  
                u = ch[u][c];  
            }  
            if(val[u]) time[val[u]]++;  
            else val[u] = v,time[v] = 1;  
        }  


        void print(int j)  
        {  
            if(j)   
            {  
                //if(!cnt[val[j]]) 
    num += time[val[j]];  
                cnt[val[j]]++;  
                print(last[j]);  
            }  
        }  


        void find(char *T)  
        {  
            int n = strlen(T);  
            int j = 0;  
            for(int i = 0;i < n;i++)  
            {  
                int c = idx(T[i]);  
                j = ch[j][c];  
                if(val[j]) print(j);  
                else if(last[j]) print(last[j]);  
            }  
        }  


        void getFail()  
        {  
            queue<int> q;  
            f[0] = 0;  
            for(int c = 0;c < 26;c++)  
            {  
                int u = ch[0][c];  
                if(u)  
                {  
                    f[u] = 0;  
                    q.push(u);  
                    last[u] = 0;  
                }  
            }  


            while(!q.empty())  
            {  
                int r = q.front();
                q.pop();  
                for(int c = 0;c < 26;c++)  
                {  
                    int u = ch[r][c];  
                    if(!u)  
                    {  
                        ch[r][c] = ch[f[r]][c];  
                        continue;  
                    }  
                    q.push(u);   
                    f[u] = ch[f[r]][c];  
                    last[u] = val[f[u]] ? f[u] : last[f[u]];  
                }  
            }  
        }  
    } tree;  


    int main()  
    {  
        cin>>T;
        while(T--)  
        {  
            tree.init();
    scanf("%s",str);    
            cin>>n;  
            for(int i = 1;i <= n;i++)  
            {  
                scanf("%s",s);  
                tree.insert(s,i);  
            }  
            tree.getFail();  
            tree.find(str);  
            cout<<tree.num<<endl;  
        }  
        return 0;
    }   



  • 相关阅读:
    笔记
    BlangenOA项目展示(附源码)
    笔记截至20190406
    ASP.NET MVC 使用过滤器需要注意
    单例模式和HttpContext线程内唯一
    C#线程/进程同步(lock、Mutex、Semaphore)
    Web标准
    JavaScript 放置在文档最后面可以使页面加载速度更快
    GUI 面板实现 (解决了关闭事件)
    GUI 实现多个窗口 (使用封装特性)
  • 原文地址:https://www.cnblogs.com/csushl/p/9386521.html
Copyright © 2011-2022 走看看