3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 4057 Solved: 1964
[Submit][Status][Discuss]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
a
aa
aaa
Sample Output
6
3
1
3
1
HINT
Source
这题把fail指针逆向形成了一个叫fail树的东西 fail树的父亲结点一定是儿子节点的子串!!!
1 #include "bits/stdc++.h" 2 using namespace std; 3 typedef long long LL; 4 const int MAX=1000006; 5 int n; 6 struct Aho{ 7 struct state{ 8 int next[26]; 9 int cnt,fail; 10 state (){ 11 memset(next,0,sizeof(next)); 12 cnt=fail=0; 13 } 14 }sst[MAX]; 15 16 int q[MAX],low,high,tot,size,end[205],sum[MAX]; 17 18 void init(){ 19 int i,j; 20 low=1,high=tot=size=0; 21 memset(sum,0,sizeof(sum)); 22 } 23 24 void insert(char *s){ 25 int i,j,ls=strlen(s); 26 int now=0; 27 for (i=0;i<ls;i++){ 28 char c=s[i]; 29 if (!sst[now].next[c-'a']) sst[now].next[c-'a']=++size; 30 now=sst[now].next[c-'a']; 31 sum[now]++; 32 } 33 sst[now].cnt++; 34 end[++tot]=now; 35 } 36 37 void build(){ 38 int i,j; 39 int now=0; 40 sst[0].fail=-1; 41 q[++high]=0; 42 while (low<=high){ 43 int u=q[low]; 44 low++; 45 for (i=0;i<26;i++){ 46 if (sst[u].next[i]){ 47 if (u==0) sst[sst[u].next[i]].fail=0; 48 else{ 49 int v=sst[u].fail; 50 while (v!=-1){ 51 if (sst[v].next[i]){//注意 52 sst[sst[u].next[i]].fail=sst[v].next[i]; 53 break; 54 } 55 v=sst[v].fail; 56 } 57 if (v==-1) 58 sst[sst[u].next[i]].fail=0; 59 } 60 q[++high]=sst[u].next[i]; 61 } 62 } 63 } 64 for (;high;high--) sum[sst[q[high]].fail]+=sum[q[high]];//注意 65 } 66 }aho; 67 int main(){ 68 freopen ("word.in","r",stdin); 69 freopen ("word.out","w",stdout); 70 int i,j;char s[MAX]; 71 aho.init(); 72 scanf("%d\n",&n); 73 for (i=1;i<=n;i++){ 74 gets(s); 75 aho.insert(s); 76 } 77 aho.build(); 78 for (i=1;i<=n;i++){ 79 printf("%d\n",aho.sum[aho.end[i]]); 80 } 81 return 0; 82 }
未来是什么样,未来会发生什么,谁也不知道。
但是我知道,
起码从今天开始努力,
肯定比从明天开始努力,
要快一天实现梦想。
千里之行,始于足下! ——《那年那兔那些事儿》