关键词匹配(Ac自动机模板题)

来源:互联网 发布:拟线性偏好知乎 编辑:程序博客网 时间:2024/05/01 11:50

2772: 关键词匹配

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 10  Solved: 4
[Submit][Status][Web Board]

Description

给你N个单词,然后给定一个字符串,问一共有多少单词在这个字符串中出现过(输入相同的字符串算不同的单词,同一个单词重复出现只计一次)。

Input

第一行一个整数N,表示给定单词的个数。
接下来N行,每行输入一个长度不超过50且全由小写字母组成的单词。
最后一行输入一个长度不超过1000000的字符串。
N≤10000

Output

输出一行包含一个整数,表示共在给定字符串中出现过的单词个数。

Sample Input

5shehesayshrheryasherhs​

Sample Output

3

HINT

 

Source

 题解:

  裸Ac自动机,不会的可以去看看这个博客:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html;

 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define maxn 1000005 5 #define maxm 1000005 6 using namespace std; 7 int n,tot,head,tail,son[maxm][26],fai[maxm],sum[maxm],list[maxm]; 8 char s[maxn]; 9 void clear(){10         tot=0;11         memset(son,0,sizeof(son));12         memset(sum,0,sizeof(sum));13     }14     void insert(char *s){15         int p=0;16         for (int i=1;s[i];p=son[p][s[i]-'a'],i++) if (!son[p][s[i]-'a']) son[p][s[i]-'a']=++tot;17         sum[p]++;18     }19     void failed(){20         head=0,tail=1,list[1]=0,fai[0]=-1;21         while (head!=tail){22             int x=list[++head];23             for (int ch=0;ch<26;ch++)24                 if (son[x][ch]){25                     list[++tail]=son[x][ch];26                     int p=fai[x];27                     while (p!=-1&&!son[p][ch]) p=fai[p];28                     if (p==-1) fai[son[x][ch]]=0;29                     else fai[son[x][ch]]=son[p][ch];30                 }   31         }32     }33     void work(char *s){34         int ans=0;35         for (int i=1,p=0;s[i];i++){36             while (p&&!son[p][s[i]-'a']) p=fai[p];37             p=son[p][s[i]-'a'];38             for (int t=p;t;t=fai[t]) ans+=sum[t],sum[t]=0;39         }40         printf("%d\n",ans);41     }42 int main()43 {44         cin>>n;//,clear();45         for (int i=1;i<=n;i++) scanf("%s",s+1),insert(s);46         failed();47         scanf("%s",s+1),work(s);48     return 0;49 }
View Code

 

 
0 0