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

 type node=record
po,next:longint;
end; var e:array[..] of node;
trie:array[..,'a'..'z'] of longint;
q,f,p,w:array[..] of longint;
v:array[..] of longint;
t,i,j,k,n,l,len:longint;
s:ansistring; procedure add(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end; procedure bfs;
var x,y,h,r,j:longint;
c:char;
begin
h:=;
r:=;
for c:='a' to 'z' do
if trie[,c]> then
begin
add(,trie[,c]);
inc(r);
q[r]:=trie[,c];
end; while h<=r do
begin
x:=q[h];
for c:='a' to 'z' do
if trie[x,c]> then
begin
y:=trie[x,c];
inc(r);
q[r]:=y;
j:=f[x];
while (j>) and (trie[j,c]=) do j:=f[j];
f[y]:=trie[j,c];
add(trie[j,c],y);
end;
inc(h);
end;
end; procedure dfs(x:longint);
var i,y:longint;
begin
i:=p[x];
while i<> do
begin
y:=e[i].po;
dfs(y);
w[x]:=w[y]+w[x];
i:=e[i].next;
end;
end; begin
readln(n);
for i:= to n do
begin
readln(s);
j:=;
l:=length(s);
for k:= to l do
begin
if trie[j,s[k]]= then
begin
inc(t);
trie[j,s[k]]:=t;
end;
j:=trie[j,s[k]];
inc(w[j]);
end;
v[i]:=j;
end;
bfs;
dfs();
for i:= to n do
writeln(w[v[i]]);
end.

ac自动机

 var h,rank,x,y,sum,sa:array[..] of longint;
f:array[..,..] of longint;
where,len,d:array[..] of longint;
now, k,ans,i,j,p,n,m,t,l,r:longint;
s,cc:ansistring;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; function lcp(a,b:longint):longint;
var k:longint;
begin
k:=trunc(ln(b-a+)/ln());
exit(min(f[a,k],f[b-d[k]+,k]));
end; begin
readln(t);
for i:= to t do
begin
readln(cc);
where[i]:=length(s)+;
len[i]:=length(cc);
s:=s+cc;
if i<>t then s:=s+' ';
end;
{ for i:=1 to t do
writeln(where[i],' ',len[i]);}
n:=length(s);
for i:= to n do
begin
y[i]:=ord(s[i]);
inc(sum[y[i]]);
end;
m:=;
for i:= to do
inc(sum[i],sum[i-]);
for i:= to n do
begin
sa[sum[y[i]]]:=i;
dec(sum[y[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if y[sa[i]]<>y[sa[i-]] then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=;
while m<n do
begin
y:=rank;
fillchar(sum,sizeof(sum),);
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i]>j then
begin
inc(p);
x[p]:=sa[i]-j;
end;
for i:= to n do
begin
rank[i]:=y[x[i]];
inc(sum[rank[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[rank[i]]]:=x[i];
dec(sum[rank[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i]+j]<>y[sa[i-]+j]) then inc(p);
rank[sa[i]]:=p;
end;
j:=j shl ;
m:=p;
end;
h[]:=;
p:=;
for i:= to n do
begin
if rank[i]= then continue;
j:=sa[rank[i]-];
while s[i+p]=s[j+p] do inc(p);
h[rank[i]]:=p;
if p> then dec(p);
end;
k:=trunc(ln(n)/ln());
d[]:=;
for i:= to k do
d[i]:=d[i-]*;
for i:= to n do
f[i,]:=h[i];
for j:= to k do
for i:= to n do
if i+d[j]-<=n then
begin
f[i,j]:=min(f[i,j-],f[i+d[j-],j-]);
end
else break;
for i:= to t do
begin
ans:=;
k:=-;
l:=;
now:=rank[where[i]];
r:=now-;
while l<=r do
begin
m:=(l+r) shr ;
if lcp(m+,now)>=len[i] then
begin
k:=m;
r:=m-
end
else l:=m+;
end;
if k<>- then ans:=ans+now-k;
l:=now+;
k:=-;
r:=n;
while l<=r do
begin
m:=(l+r) shr ;
if lcp(now+,m)>=len[i] then
begin
k:=m;
l:=m+;
end
else r:=m-;
end;
if k<>- then ans:=ans+k-now;
writeln(ans);
end;
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. jQuery $.each的使用方法

    通过jQuery $.each,你可以遍历对象.数组的属性值并进行处理. 使用说明 each函数根据参数的类型实现的效果不完全一致: 1.遍历对象(有附加参数) $.each(Object, func ...

  2. javascript面向对象程序设计系列(一)---创建对象

    javascript是一种基于对象的语言,但它没有类的概念,所以又和实际面向对象的语言有区别,面向对象是javascript中的难点之一.现在就我所理解的总结一下,便于以后复习: 一.创建对象 1.创 ...

  3. 数据挖掘-关联规则分析[ZZ]

    1.什么是关联规则 "尿布与啤酒"的故事大家都有听过,这里就不罗嗦了. 按常规思维,尿布与啤酒风马牛不相及,若不是借助数据挖掘技术对大量交易数据进行挖掘分析,沃尔玛是不可能发现数据 ...

  4. Codevs 1702 素数判定 2(Fermat定理)

    1702 素数判定 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 一个数,他是素数么? 设他为P满足(P< ...

  5. Win7下Boost库的安装

    Boost库是C++领域公认的经过千锤百炼的知名C++类库,涉及编程中的方方面面,简单记录一下使用时的安装过程 1.boost库的下载 boost库官网主页:www.boost.org 2.安装 将下 ...

  6. 深度优化LNMP之Nginx [2]

    深度优化LNMP之Nginx [2]   配置Nginx gzip 压缩实现性能优化 1.Nginx gzip压缩功能介绍        Nginx gzuo压缩模块提供了压缩文件内容的功能,用户请求 ...

  7. document.getElementById获取不到标签值

    var apliay=document.getElementById('apliay_ok'); 代码里指定有id="apliay_ok"的标签,但是获取不到,折腾半天原来是因为在 ...

  8. mongodb篇二:mongodb克隆远程数据库,去重查询的命令及对应java语句

    http://blog.csdn.net/qkxh320/article/details/16115671 1.首先操作mongodb最基本命令:: show databases;           ...

  9. sql性能优化总结(转)

    网上看到一篇sql优化的文章,整理了一下,发现很不错,虽然知道其中的部分,但是没有这么全面的总结分析过…… 一.   目的 数据库参数进行优化所获得的性能提升全部加起来只占数据库应用系统性能提升的40 ...

  10. Codeforces Round #336 (Div. 1) A - Chain Reaction

    Chain Reaction 题意:有n(1 ≤ n ≤ 100 000) 个灯泡,每个灯泡有一个位置a以及向左照亮的范围b (0 <= a <= 1e6 ,1<= b <= ...