[BZOJ3172][TJOI2013]单词(AC自动机+fail树)

来源:互联网 发布:aerial mac 不能播放 编辑:程序博客网 时间:2024/05/16 09:37

题目:

我是超链接

题解:

建立fail树,节点大小维护为出现的次数

fail树:以x节点结尾的字符串在x节点的子树里

qurry数组是由深及浅的控制,以免漏加*加重

代码:

#include <cstdio>#include <algorithm>#include <cstring>#include <queue>using namespace std;const int N=1e6;char st[N+5];int ch[N+5][27],ans[N+5],tot=0,qurry[N+5],fail[N+5],cnt=0,pos[N+5];void trie(int &loc){scanf("%s",st);int i=0,l=strlen(st),now=0;for (i=0;i<l;i++)  {  int x=st[i]-'a';  if (!ch[now][x]) ch[now][x]=++tot;now=ch[now][x];++ans[now];  }loc=now;}void sp(){queue <int> q; for (int i=0;i<26;++i)      if (ch[0][i])        q.push(ch[0][i]);while (!q.empty()){int now=q.front(); q.pop();qurry[++cnt]=now;for (int i=0;i<26;i++){if (!ch[now][i]){ch[now][i]=ch[fail[now]][i];continue;}fail[ch[now][i]]=ch[fail[now]][i];q.push(ch[now][i]);}}}void ask(){int i;for (i=cnt;i>=1;i--)   ans[fail[qurry[i]]]+=ans[qurry[i]];}int main(){int i,n;scanf("%d",&n);for (i=1;i<=n;i++)  trie(pos[i]);sp();ask();for (i=1;i<=n;i++)  printf("%d\n",ans[pos[i]]);}


0 0
原创粉丝点击