HDU-2222 Keywords Search(AC自动机)

来源:互联网 发布:淘宝618活动怎么报名 编辑:程序博客网 时间:2024/05/01 02:51

Keywords Search

http://acm.hdu.edu.cn/showproblem.php?pid=2222

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description
In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
 

Input
First line will contain one integer means how many cases will follow by.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.
 

Output
Print how many keywords are contained in the description.
 

Sample Input
15shehesayshrheryasherhs
 

Sample Output
3

AC自动机代码简单又容易理解,终于明白为什么写Trie图的那么少了

#include <cstdio>#include <queue>using namespace std;const int MAXNODE=10000*50+5;int T,n;char s[1000005];struct Trie {    int nxt[MAXNODE][26],fail[MAXNODE],ed[MAXNODE];//数组模拟    int l;    const static int root=0;    Trie() {       clear();    }    int newNode() {//取一个结点        for(int i=0;i<26;++i)            nxt[l][i]=-1;        ed[l]=0;//ed[l]表示从根到当前结点的模式串出现的次数        return l++;    }    void insert(char *p) {//插入一个模式串        int cur=root;        while(*p) {            if(nxt[cur][*p-'a']==-1)                nxt[cur][*p-'a']=newNode();            cur=nxt[cur][*p-'a'];            ++p;        }        ++ed[cur];    }    void build() {//建立fail指针        int cur,i;        queue<int> q;        fail[root]=root;        for(i=0;i<26;++i)            if(nxt[root][i]==-1)//如果根结点无i子结点                nxt[root][i]=root;            else {                fail[nxt[root][i]]=root;                q.push(nxt[root][i]);            }        while(!q.empty()) {            cur=q.front();            q.pop();            for(i=0;i<26;++i)                if(nxt[cur][i]==-1)//如果当前结点无i子结点                    nxt[cur][i]=nxt[fail[cur]][i];//当前结点的i子结点指针 指向 当前结点fail指针指向的结点的i子结点                else {                    fail[nxt[cur][i]]=nxt[fail[cur]][i];//当前结点i子结点的fail指针 指向 当前结点fail指针指向的结点的i子结点                    q.push(nxt[cur][i]);                }        }    }    int query(char *p) {        int cur=root,ans=0,tmp;        while(*p) {            cur=nxt[cur][*p-'a'];            tmp=cur;            while(tmp!=root) {//遍历与当前形成的串有公共后缀的串                ans+=ed[tmp];                ed[tmp]=0;//由于只需要统计出现了关键词,所需需要置0,防止重复计算                tmp=fail[tmp];            }            ++p;        }        return ans;    }    void clear() {        l=root;        newNode();    }}ac;int main() {    scanf("%d",&T);    while(T--) {        ac.clear();        scanf("%d",&n);        while(n--) {            scanf("%s",s);            ac.insert(s);        }        ac.build();        scanf("%s",s);        printf("%d\n",ac.query(s));    }    return 0;}


0 0
原创粉丝点击