[BZOJ3172]单词
Posted LadyLex
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3172]单词相关的知识,希望对你有一定的参考价值。
3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MBDescription
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
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
题解:
这道题相对来说比较简单……
我们可以建好AC自动机,然后像后缀数组一样,把每一个串用‘&’连起来。
像这样:“aaa&aa&a”
然后拿这个大串去AC自动机里面统计次数就好了。
代码见下:
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 using namespace std; 5 const int L=100010; 6 char text[210*L],s[210][L]; 7 int n,p=-1,hd=1,tl; 8 long long ans[210]; 9 struct node 10 { 11 vector<int>val;node *last,*f,*ch[26]; 12 node(){memset(ch,0,sizeof(ch));val.clear();} 13 void* operator new(size_t); 14 }*root=new node(),*c,*num,*q[L*210]; 15 void* node::operator new(size_t) 16 { 17 if(c==num) 18 { 19 c=new node::node[1<<10]; 20 memset(c,0,sizeof(node)*(1<<10)); 21 num=c+(1<<10); 22 } 23 return c++; 24 } 25 inline void count(node* pos) 26 { 27 while(pos) 28 { 29 for(int i=0;i<pos->val.size();i++) 30 ans[pos->val[i]]++; 31 pos=pos->last; 32 } 33 } 34 inline void get_fail() 35 { 36 root->f=NULL;root->last=NULL;q[++tl]=root; 37 while(hd<=tl) 38 { 39 node *rt=q[hd++]; 40 for(int i=0;i<26;i++) 41 { 42 if(rt->ch[i]) 43 { 44 q[++tl]=rt->ch[i]; 45 node *u=rt->f; 46 while(u&&!u->ch[i])u=u->f; 47 rt->ch[i]->f=(u)?u->ch[i]:root; 48 rt->ch[i]->last=rt->ch[i]->f->val.empty()?rt->ch[i]->f->last:rt->ch[i]->f; 49 } 50 } 51 } 52 } 53 inline void match() 54 { 55 node *rt=root; 56 for(int i=0;i<p;i++) 57 { 58 if(text[i]==‘&‘)rt=root; 59 else 60 { 61 int d=text[i]-‘a‘; 62 while(rt&&!rt->ch[d])rt=rt->f; 63 rt=rt?rt->ch[d]:root; 64 count(rt); 65 } 66 } 67 } 68 int main() 69 { 70 scanf("%d",&n); 71 for(int i=1;i<=n;i++) 72 { 73 scanf("%s",s[i]);int m=strlen(s[i]); 74 node* rt=root; 75 for(int j=0;j<m;j++) 76 { 77 text[++p]=s[i][j]; 78 if(!rt->ch[s[i][j]-‘a‘]) 79 rt->ch[s[i][j]-‘a‘]=new node(); 80 rt=rt->ch[s[i][j]-‘a‘]; 81 } 82 rt->val.push_back(i);text[++p]=‘&‘; 83 } 84 get_fail();match(); 85 for(int i=1;i<=n;i++)printf("%lld\n",ans[i]); 86 }
以上是关于[BZOJ3172]单词的主要内容,如果未能解决你的问题,请参考以下文章