题面:

洛谷

题解:

  很久之前做的题了,只不过之前一直90.。。。最近才发现是哪里写错了。

  我们对字符集建AC自动机。

  首先考虑一个暴力的做法,把文章当做一个长串,直接在自动机上跳,但是我们会发现,这样的复杂度可能退化到$n^2$.

  因为对于一个类似于aaaaaaaaaaaaaaaa这样的串而言,一个点的fail总是指向它的父亲,因此如果我们每次都暴力向上跳fail复杂度就不对了。

  观察到每遍历到一个节点,其实质就是给这个点到root的这条链上的每个点都+1,因此我们目标只是在fail树上对每个点都求出子树和。

  如果我们知道了所有标记的位置,显然可以建树统计一下。

  当然,也有更方便的写法,因为一个点的编号肯定比它的fail的编号大。表现在fail树上就是父亲编号比儿子小。

  所以我们从大到小枚举编号,把当前枚举到的节点的权值加给父亲即可。

  为什么这样是对的?

    因为我们可以看做是儿子先把代价给父亲,在让父亲把它的代价和它儿子的代价一起向上传。

  

  其实对于这道题而言,还有更方便的写法,你甚至不需要建匹配串。因为文章就是由给定字符集组成的,因此我们一定会遍历自动机上的每一个节点,所以与其再遍历一遍,再把每个节点权值+1,不如在建自动机的时候就直接加。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define maxn 2500500
int n,ans[maxn],go[maxn],num;//num标记是第一个单词,便于处理单词重复的情况
int q[maxn],head,tail,tot;//从第一位开始存文本串
char s[maxn]; struct ACtree
{
int fail[maxn], c[maxn][];
//由于是统计单词在文章中的出现次数,相同单词只算一次,所以val最大只能为1
void add()//标记是第一个单词
{
int now=,len=strlen(s);
for(R i=;i<len;i++)
{
int v=s[i]-'a';
if(!c[now][v]) c[now][v]=++tot;
now=c[now][v], ++ ans[now];//因为之后再遍历也是直接遍历整个树,所以直接在这里加
}
// if(!val[now])val[now]++;//这样val就没用了
go[num]=now;//记录下每个单词的结尾部分,以防遇到重复只输出一个
} void build()
{
R now;
for(R i=; i< ;i++)
if(c[][i]) q[++tail]=c[][i];//既然fail一开始都为0,那就不用额外初始化了
while(head<tail)
{
now=q[++head];
for(R i=;i<;i++)
if(c[now][i]) fail[c[now][i]]=c[fail[now]][i],q[++tail]=c[now][i];
else c[now][i]=c[fail[now]][i];//建立虚拟节点
}
for(R i = tail; i; i --) ans[fail[q[i]]] += ans[q[i]];
for(R i = ; i <= n; i ++) printf("%d\n", ans[go[i]]);
} }AC; void pre()
{
scanf("%d",&n);
for(num=; num<=n ;num++)
scanf("%s",s), AC.add();
} int main()
{
// freopen("in.in","r",stdin);
pre();
AC.build();
// fclose(stdin);
return ;
}

  

最新文章

  1. JavaScript鼠标经过图片的放大镜效果
  2. C语言 &#183; 回文数
  3. http://www.aboutyun.com/thread-6551-1-1.html
  4. jquery easy ui 学习 (9)Pagination in TreeGrid 分页
  5. Spark里面的任务调度:离SparkContext开始
  6. Visual Studio Team Services使用教程--Readers tfs组成员添加
  7. PS-前端切图教程(切jpg图和切png图)
  8. js结合方式:
  9. mybatis逆向工程没有报错,但是也没有pojo和Mapper文件问题
  10. 个人项目Week1
  11. 014.Docker Harbor+Keepalived+LVS+共享存储高可用架构
  12. swift -inout关键字
  13. Camtasia studio8.0破解方法
  14. 菜鸟学Java(十六)——Jboss简介
  15. base64 与字符串互转
  16. 在eclipse中,用maven创建web项目
  17. eclipse创建文件package,source folder和folder区别及相互转换
  18. Java 集合框架必记框架图
  19. bzoj 1089 SCOI2003严格n元树 递推
  20. Kestrel Web 服务器学习笔记

热门文章

  1. django使用流程
  2. 写一个 setter 方法用于完成 @property (nonatomic, retain) NSString *name,
  3. Struts 2(七):国际化
  4. vbox虚拟机扩容(CentOS 7.2)
  5. HTML5 + CSS3 实现地球绕太阳公转
  6. 11-Dockerfile构建镜像
  7. Python中如何实现im2col和col2im函数(sliding类型)
  8. 1.openldap介绍
  9. ES6的新特性(8)——数组的扩展
  10. 【java】中缀表达式转后缀表达式 java实现