传送门

题目大意

给定文本串$S$和若干模式串$\{T\}$, 对每个模式串$T$, 询问$T$是否为$S$的子串.

Solution

裸的AC自动机, 也可以用后缀数组做.

P.S. 这题数据很弱, 朴素的字符串匹配也能过.

Pitfalls

模式串有重复的. 这样, 在建TRIE时就不能直接对每个模式串对应的节点 (尾节点) 标记上模式串的序号, 否则对于重复出现的模式串, 最后一次出现的那个会把在它之前的那些覆盖掉.

正确的做法是, 对于每个尾节点作唯一标号. 另外维护一个表$idx[]$, $idx[i]$表示第$i$个模式串的尾节点的标号.

另外要注意AC自动机的某些易错的实现细节, 代码注释有提及.

Implementation

注释比较详细, 可作为模板.

 #include <bits/stdc++.h>
using namespace std; const int N{<<}, M{<<}; bool res[M];
int idx[M];
char s[N], t[M];
int ch[N][], id[N], fail[N], last[N]; int get_id(char ch){
return islower(ch)?ch-'a':ch-'A'+;
} queue<int> que; int main(){
// cout<<int('a')<<' '<<int('z')<<' '<<int('A')<<' '<<int('Z')<<endl;
int T;
for(cin>>T; T--; ){
int q;
scanf("%s%d", s, &q);
int tail=; memset(res, false, sizeof(res)); //error-prone memset(ch[tail], , sizeof(ch[tail]));
tail++; for(int i=; i<=q; i++){
scanf("%s", t);
int u=;
for(int j=; t[j]; j++){
int &v=ch[u][get_id(t[j])];
if(!v){
v=tail++;
memset(ch[v], , sizeof(ch[v]));
id[v]=;
}
u=v;
}
if(!id[u]) id[u]=i; //error-prone: possibly duplicate patterns
idx[i]=id[u];
} for(int i=; i<; i++){
int u=ch[][i];
if(u){
que.push(u);
fail[u]=last[u]=; //error-prone, must be initialized!!
}
} for(; que.size(); ){
int u=que.front();
que.pop();
for(int i=; i<; i++){
//!view a variable (object) as an entity
int &v=ch[u][i];
if(v){ //v is a new node, construct a new node of AC automata
que.push(v);
//no need to init. last[] and fail[], as they are is induced.
fail[v]=ch[fail[u]][i];
last[v]=id[fail[v]]?fail[v]:last[fail[v]];
}
else{ //the expected node v does not exist
v=ch[fail[u]][i];
}
}
} for(int i=, u=; s[i]; i++){
u=ch[u][get_id(s[i])];
res[id[u]]=true;
for(int v=last[u]; v; res[id[v]]=true, v=last[v]); //error-prone
} for(int i=; i<=q; i++)
puts(res[idx[i]]?"y":"n"); }
}

 UPD

上面代码中第76行

 for(int v=last[u]; v; res[id[v]]=true, v=last[v]); 

可优化为

 for(int v=last[u]; v && !res[id[v]]; res[id[v]]=true, v=last[v]); 

这样可保证每个单词节点(dictionary node)通过last指针(dictionary suffix link) 的访问次数为至多为1 ,从而提高时间效率。


上穷碧落下黄泉.

UVA 10679 I Love Strings的更多相关文章

  1. UVA 10679 I love Strings!!!(AC自己主动机)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  2. UVa OJ 455 Periodic Strings

     Periodic Strings  A character string is said to have period k if it can be formed by concatenating ...

  3. lightoj 1052 - String Growth & uva 12045 - Fun with Strings 矩阵

    思路:很容易发现规律,数列和Fib数列一样的. 记开始的时候啊a的个数为Y,b的个数为X.建立矩阵. 代码如下: #include<iostream> #include<cstdio ...

  4. 【习题 3-4 UVA - 455】Periodic Strings

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举 [代码] #include <bits/stdc++.h> using namespace std; const ...

  5. UVa 455 - Periodic Strings解题报告

    UVa OJ 455 Periodic Strings A character string is said to have period k if it can be formed by conca ...

  6. 一位学长的ACM总结(感触颇深)

    发信人: fennec (fennec), 信区: Algorithm 标 题: acm 总结 by fennec 发信站: 吉林大学牡丹园站 (Wed Dec 8 16:27:55 2004) AC ...

  7. UVA.455 Periodic Strings(字符串的最小周期)

    Periodic Strings 模板 题意分析 判断字符串的最小周期 代码总览 /* Title:UVA.455 Author:pengwill Date:2016-12-16 */ #includ ...

  8. uva 11081 - Strings(LCS)

    题目链接:11081 - Strings 题目大意:给出三个字符串,从分别从第一个字符串和第二个字符串中挑选子串a,b,用a和b组成第三个字符串,问可组成的子串有多少种. 解题思路:说起来惭愧啊,题目 ...

  9. UVA - 10298 Power Strings (KMP求字符串循环节)

    Description Problem D: Power Strings Given two strings a and b we define a*b to be their concatenati ...

随机推荐

  1. 某站出品2016织梦CMS进阶教程共12课(附文档+工具)

    此为广告商内容使用最新版的dede cms建站 V5.7 sp1,经常注意后台的升级信息哦!一.安装DEDE的时候数据库的表前缀,最好改一下,不用dedecms默认的前缀dede_,随便一个名称即可. ...

  2. 后记:Cookie安全大辩论总结

    前天,我发布在博客园上的某知名电商网站的Cookie漏洞引发园友们的热议,学到了很多知识,现在整理一下其中比较激烈的技术讨论.谁对谁错每个人自己心中都有一把称,很多时候都是我无法说服你,你也无法说服我 ...

  3. C#基础之IEnumerable

    1.IEnumerable的作用 在使用Linq查询数据时经常以IEnumerable<T>来作为数据查询返回对象,在使用foreach进行遍历时需要该对象实现IEnumerable接口, ...

  4. 在nodeJs的Express框架下用TypeScript编写router路由出现import关键字错误的解决方案

    问题出现场景 在项目中采用nodejs做中间层,做页面的首屏渲染,同时采用express作为主web框架,其中express的router页面路由我采用ts语言来编写.如下: //page.ts 文件 ...

  5. canvas 2d 贴图技术实践

    最近在公司内部的技术协会论坛里闲逛的时候,无意中发现了一篇手淘前端大牛岑安两年前写的博文,讲述了canvas的2d贴图技术.看到后觉得相当神奇.于是就自己实现了一下.不过岑安前辈的那篇博文也只是大概讲 ...

  6. sql server存储过程编程

    存储过程是一组完成特定功能的SQL 语句集合,经编译后存储在数据库中.   存储过程作为一个单元进行处理并以一个名称来标识.它能向用户返回数据.向数据库表中写入或修改数据等操作. 用户通过指定存储过程 ...

  7. crontab 定时任务

    1 linux 系统需要安装crontab ;yum install vixie-cron crontabs 2 编写shell 脚本, save_dir=/var/local/mysqlbak/Ne ...

  8. 【Magenta 项目初探】手把手教你用Tensorflow神经网络创造音乐

    原文链接:http://www.cnblogs.com/learn-to-rock/p/5677458.html 偶然在网上看到了一个让我很感兴趣的项目 Magenta,用Tensorflow让神经网 ...

  9. Graphql介绍(Introduction to GraphQL)

    Introduction to GraphQL  GraphQL介绍 Learn about GraphQL, how it works, and how to use it in this seri ...

  10. Linux14.04安装Mysql Linux公社

    今天在Ubuntu 14.04下安装MySQL,本来是去官网下载安装包来安装的,可是安装之后却不能用,估计是要配置吧,在网上搜了很多的资料,结果还是失败.所以只好在软件源中安装,这样就省去很多不必要的 ...