这里学习AC自动机
其实对KMP和trie掌握好了之后很容易扩展成AC自动机的
这里运用了一个性质
由失配指针反向可以建成一棵fail树
x串在y串中的出现的次数即为在fail树上以x结尾节点为根的子树中有多少个节点属于y串,这很好理解
而推广到这题,在文章中出现的次数即为单词结尾节点为根的子树的规模
注意这道题有相同的单词
当初这题我是用后缀数组做的O(LlogL)
而自动机复杂度为O(L),快了很多

  1. type node=record
  2. po,next:longint;
  3. end;
  4.  
  5. var e:array[..] of node;
  6. trie:array[..,'a'..'z'] of longint;
  7. q,f,p,w:array[..] of longint;
  8. v:array[..] of longint;
  9. t,i,j,k,n,l,len:longint;
  10. s:ansistring;
  11.  
  12. procedure add(x,y:longint);
  13. begin
  14. inc(len);
  15. e[len].po:=y;
  16. e[len].next:=p[x];
  17. p[x]:=len;
  18. end;
  19.  
  20. procedure bfs;
  21. var x,y,h,r,j:longint;
  22. c:char;
  23. begin
  24. h:=;
  25. r:=;
  26. for c:='a' to 'z' do
  27. if trie[,c]> then
  28. begin
  29. add(,trie[,c]);
  30. inc(r);
  31. q[r]:=trie[,c];
  32. end;
  33.  
  34. while h<=r do
  35. begin
  36. x:=q[h];
  37. for c:='a' to 'z' do
  38. if trie[x,c]> then
  39. begin
  40. y:=trie[x,c];
  41. inc(r);
  42. q[r]:=y;
  43. j:=f[x];
  44. while (j>) and (trie[j,c]=) do j:=f[j];
  45. f[y]:=trie[j,c];
  46. add(trie[j,c],y);
  47. end;
  48. inc(h);
  49. end;
  50. end;
  51.  
  52. procedure dfs(x:longint);
  53. var i,y:longint;
  54. begin
  55. i:=p[x];
  56. while i<> do
  57. begin
  58. y:=e[i].po;
  59. dfs(y);
  60. w[x]:=w[y]+w[x];
  61. i:=e[i].next;
  62. end;
  63. end;
  64.  
  65. begin
  66. readln(n);
  67. for i:= to n do
  68. begin
  69. readln(s);
  70. j:=;
  71. l:=length(s);
  72. for k:= to l do
  73. begin
  74. if trie[j,s[k]]= then
  75. begin
  76. inc(t);
  77. trie[j,s[k]]:=t;
  78. end;
  79. j:=trie[j,s[k]];
  80. inc(w[j]);
  81. end;
  82. v[i]:=j;
  83. end;
  84. bfs;
  85. dfs();
  86. for i:= to n do
  87. writeln(w[v[i]]);
  88. end.

ac自动机

  1. var h,rank,x,y,sum,sa:array[..] of longint;
  2. f:array[..,..] of longint;
  3. where,len,d:array[..] of longint;
  4. now, k,ans,i,j,p,n,m,t,l,r:longint;
  5. s,cc:ansistring;
  6. function min(a,b:longint):longint;
  7. begin
  8. if a>b then exit(b) else exit(a);
  9. end;
  10.  
  11. function lcp(a,b:longint):longint;
  12. var k:longint;
  13. begin
  14. k:=trunc(ln(b-a+)/ln());
  15. exit(min(f[a,k],f[b-d[k]+,k]));
  16. end;
  17.  
  18. begin
  19. readln(t);
  20. for i:= to t do
  21. begin
  22. readln(cc);
  23. where[i]:=length(s)+;
  24. len[i]:=length(cc);
  25. s:=s+cc;
  26. if i<>t then s:=s+' ';
  27. end;
  28. { for i:=1 to t do
  29. writeln(where[i],' ',len[i]);}
  30. n:=length(s);
  31. for i:= to n do
  32. begin
  33. y[i]:=ord(s[i]);
  34. inc(sum[y[i]]);
  35. end;
  36. m:=;
  37. for i:= to do
  38. inc(sum[i],sum[i-]);
  39. for i:= to n do
  40. begin
  41. sa[sum[y[i]]]:=i;
  42. dec(sum[y[i]]);
  43. end;
  44. p:=;
  45. rank[sa[]]:=;
  46. for i:= to n do
  47. begin
  48. if y[sa[i]]<>y[sa[i-]] then inc(p);
  49. rank[sa[i]]:=p;
  50. end;
  51. m:=p;
  52. j:=;
  53. while m<n do
  54. begin
  55. y:=rank;
  56. fillchar(sum,sizeof(sum),);
  57. p:=;
  58. for i:=n-j+ to n do
  59. begin
  60. inc(p);
  61. x[p]:=i;
  62. end;
  63. for i:= to n do
  64. if sa[i]>j then
  65. begin
  66. inc(p);
  67. x[p]:=sa[i]-j;
  68. end;
  69. for i:= to n do
  70. begin
  71. rank[i]:=y[x[i]];
  72. inc(sum[rank[i]]);
  73. end;
  74. for i:= to m do
  75. inc(sum[i],sum[i-]);
  76. for i:=n downto do
  77. begin
  78. sa[sum[rank[i]]]:=x[i];
  79. dec(sum[rank[i]]);
  80. end;
  81. p:=;
  82. rank[sa[]]:=;
  83. for i:= to n do
  84. begin
  85. if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i]+j]<>y[sa[i-]+j]) then inc(p);
  86. rank[sa[i]]:=p;
  87. end;
  88. j:=j shl ;
  89. m:=p;
  90. end;
  91. h[]:=;
  92. p:=;
  93. for i:= to n do
  94. begin
  95. if rank[i]= then continue;
  96. j:=sa[rank[i]-];
  97. while s[i+p]=s[j+p] do inc(p);
  98. h[rank[i]]:=p;
  99. if p> then dec(p);
  100. end;
  101. k:=trunc(ln(n)/ln());
  102. d[]:=;
  103. for i:= to k do
  104. d[i]:=d[i-]*;
  105. for i:= to n do
  106. f[i,]:=h[i];
  107. for j:= to k do
  108. for i:= to n do
  109. if i+d[j]-<=n then
  110. begin
  111. f[i,j]:=min(f[i,j-],f[i+d[j-],j-]);
  112. end
  113. else break;
  114. for i:= to t do
  115. begin
  116. ans:=;
  117. k:=-;
  118. l:=;
  119. now:=rank[where[i]];
  120. r:=now-;
  121. while l<=r do
  122. begin
  123. m:=(l+r) shr ;
  124. if lcp(m+,now)>=len[i] then
  125. begin
  126. k:=m;
  127. r:=m-
  128. end
  129. else l:=m+;
  130. end;
  131. if k<>- then ans:=ans+now-k;
  132. l:=now+;
  133. k:=-;
  134. r:=n;
  135. while l<=r do
  136. begin
  137. m:=(l+r) shr ;
  138. if lcp(now+,m)>=len[i] then
  139. begin
  140. k:=m;
  141. l:=m+;
  142. end
  143. else r:=m-;
  144. end;
  145. if k<>- then ans:=ans+k-now;
  146. writeln(ans);
  147. end;
  148. end.

后缀数组

bzoj3172的更多相关文章

  1. 【BZOJ3172】[Tjoi2013]单词 AC自动机

    [BZOJ3172][Tjoi2013]单词 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input ...

  2. 【BZOJ3172】单词(AC自动机)

    [BZOJ3172]单词(AC自动机) 题面 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input ...

  3. BZOJ3172 [Tjoi2013]单词 字符串 SA ST表

    原文链接http://www.cnblogs.com/zhouzhendong/p/9026543.html 题目传送门 - BZOJ3172 题意 输入$n(n\leq 200)$个字符串,保证长度 ...

  4. 【bzoj3172】 Tjoi2013—单词

    http://www.lydsy.com/JudgeOnline/problem.php?id=3172 (题目链接) 题意 $n$个单词组成文本,问每个单词在文本中出现了几次. Solution 题 ...

  5. [BZOJ3172]单词

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MB Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会 ...

  6. 【bzoj3172】: [Tjoi2013]单词 字符串-AC自动机

    [bzoj3172]: [Tjoi2013]单词 先用所有单词构造一个AC自动机 题目要求的是每个单词在这个AC自动机里匹配到的次数 每次insert一个单词的时候把路径上的cnt++ 那么点p-&g ...

  7. BZOJ3172&&lg3966 TJOI单词(广义后缀自动机)

    BZOJ3172&&lg3966 TJOI单词(广义后缀自动机) 题面 自己找去 HINT 给出多个文本串,让你查找每个文本串一共出现了多少次,广义后缀自动机建出parent tree ...

  8. BZOJ3172: [Tjoi2013]单词

    传送门 做了这么多题怎么还是无法很好的理解AC自动机呢..果然是个制杖 首先题意表述不是很清晰,这些所有的单词组成了那个文章,所以果断建个AC自动机,建的时候给每个点附加一个权值,建树是经过一次权值即 ...

  9. BZOJ3172——[Tjoi2013]单词

    1. 题目大意:一篇论文是由许多单词组成,现在想知道每个单词分别在论文中出现多少次. 2.分析:对着 广义后缀自动机的图看,我们就会发现玄机,答案不就是这个单词下的后缀个数吗? 于是建立自动机,然后求 ...

  10. BZOJ3172[Tjoi2013]单词 题解

    题目大意: 求一些字符串在一段文章中出现的次数. 思路: AC自动机的经典应用,建完自动机直接将队列里的元素调Fail指针记录即可. 代码: #include<cstdio> #inclu ...

随机推荐

  1. hadoop_集群安装_1

    这篇文章中主要介绍的是,如何基于VM安装Linux,以及如何在安装好Linux之后,基于操作系统安装VMTools. 在安装之前,应该先规划好 每个node*的IP地址,以及 hostname: no ...

  2. memcache的分布式算法(转)

    memcached的分布式 正如第1次中介绍的那样, memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能. 服务器端仅包括 第2次. 第3次 前坂介绍的内存存储功能,其实现 ...

  3. Object-C Dealloc

    上一篇为Object-C Init dealloc方法在一个对象从内存中删除时被调用.通常在这个方法里面释放所有对象里的实例变量 -(void)dealloc { [super dealloc]; [ ...

  4. java新手笔记17 参数

    package com.yfs.javase; public class ParamDemo { public static void main(String[] args) { int a = 3, ...

  5. Ambiguous handler methods mapped for HTTP path

    一.问题:映射重复导致的错误 java代码如下: @RequestMapping(value = "/info/{remove}/{id}", method = RequestMe ...

  6. Redis单机版以及集群版的安装搭建以及使用

    1,redis单机版 1.1   安装redis n  版本说明 本教程使用redis3.0版本.3.0版本主要增加了redis集群功能. 安装的前提条件: 需要安装gcc:yum install g ...

  7. e+开发中的各种问题

    1.数据交换后走的查询公式还是controller所配置的公式

  8. leetcode problem 32 -- Longest Valid Parentheses

    Longest Valid Parentheses Given a string containing just the characters '(' and ')', find the length ...

  9. leetcode problem (2-4)

    Problem 2 --- Add Two Numbers 简单的模拟题. Problem 3 --- Longest Substring Without Repeating Characters 题 ...

  10. jquery中的 .html(),.val().text()

    .html(),.text(),.val(),.html()用为读取和修改元素的HTML标签,包括标签内的内容.text()用来读取或修改元素的纯文本内容,去除 html 标签.val()用来读取或修 ...