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;
}   



原文地址:https://www.cnblogs.com/csushl/p/9386521.html