poj4052 Hrinity
pdf题面:传送门
题目大意:给定一些单词和一个句子,问有多少个单词在句子中出现过,如果一个但单词包含另一个单词,并且两个单词都出现过,那么只算最外层的单词(包含另一个单词的单词).
分析:这道题如果没有第二个条件的话就和hdu2222是一模一样的题.但是没关系,可以先用hdu2222的方法找出所有出现过的单词,然后每个单词将它的子串给标记.如何找一个串的子串呢?如果一个字符串s[1......n],它的子串必定在s[1......r]和s[l......n]中,也就是在前缀和后缀中,在trie里,找前缀可以利用父亲节点.找后缀可以利用AC自动机的fail指针,这样递归地标记一下就可以了.
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ,maxm = ;
char s[maxm],ss[maxm];
int T,n,cnt,tot = ,ans;
bool vis[maxn],tag[maxn],vis2[maxn]; void init()
{
n = cnt = ans = ;
memset(vis,false,sizeof(vis));
memset(vis2,false,sizeof(vis2));
memset(tag,false,sizeof(tag));
} struct node
{
int tr[],fail,id,fa;
void clear()
{
memset(tr,,sizeof(tr));
fail = id = fa = ;
}
} e[maxn]; void insert(int x)
{
int u = ;
for (int i = ; i <= cnt; i++)
{
int ch = ss[i] - 'A';
if (!e[u].tr[ch])
{
e[u].tr[ch] = ++tot;
e[tot].clear();
}
int temp = u;
u = e[u].tr[ch];
e[u].fa = temp;
}
e[u].id = x;
} void build()
{
queue <int> q;
for (int i = ; i < ; i++)
e[].tr[i] = ;
q.push();
while (!q.empty())
{
int u = q.front();
q.pop();
int fail = e[u].fail;
for (int i = ; i < ; i++)
{
int y = e[u].tr[i];
if (y)
{
e[y].fail = e[fail].tr[i];
q.push(y);
}
else
e[u].tr[i] = e[fail].tr[i];
}
}
} void dfs(int x)
{
if (tag[x])
return;
tag[x] = ;
vis[x] = ;
if (e[x].fail)
dfs(e[x].fail);
if (e[x].fa)
dfs(e[x].fa);
} bool ischar(char p)
{
return p >= 'A' && p <= 'Z';
} void getchange()
{
int len = strlen(s + );
cnt = ;
for (int i = ; i <= len; i++)
{
if (ischar(s[i]))
ss[++cnt] = s[i];
else
{
i++;
int res = ;
while (s[i] >= '' && s[i] <= '')
{
res = res * + s[i] - '';
i++;
}
char cc = s[i++];
while (res)
{
ss[++cnt] = cc;
res--;
}
}
}
} int main()
{
scanf("%d",&T);
while (T--)
{
init();
e[tot = ].clear();
scanf("%d",&n);
for (int i = ; i <= n; i++)
{
scanf("%s",s + );
getchange();
insert(i);
}
build();
scanf("%s",s + );
getchange();
int u = ;
for (int i = ; i <= cnt; i++)
{
int ch = ss[i] - 'A';
while (u && !e[u].tr[ch])
u = e[u].fail;
u = e[u].tr[ch];
int t = u;
while (t && !vis2[t])
{
vis2[t] = ;
if (e[t].id)
vis[t] = ;
t = e[t].fail;
}
} for (int i = ; i <= tot; i++)
if (!tag[i] && vis[i])
{
dfs(e[i].fail);
dfs(e[i].fa);
}
for (int i = ; i <= tot; i++)
if (vis[i])
ans++;
printf("%d\n",ans);
} return ;
}
poj4052 Hrinity的更多相关文章
- poj4052
题意:求一个文章(长度5.1e6)里面出现了多少个指定的模式串.重复出现只记一次.而且如果两个模式串都出现的情况下,一个是另一个的子串,则该子串不算出现过. 分析:AC自动机. 由于子串不算所以加一些 ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
随机推荐
- 一学就会pip换镜像源
首先介绍一个国内好用的镜像站 阿里云 http://mirrors.aliyun.com/pypi/simple/ 豆瓣 http://pypi.douban.com/simple/ 清华大学 htt ...
- 【shell 每日一练7】一键安装mysql5.7,以及密码及策略修改
一.一键安装Mysql脚本 [root@uat01 ~]# cat InstallMysql01.sh #!/bin/bash #-- #旅行者-Travel #.安装wget yum -y inst ...
- 数据库mysql的常规操作
1. 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. 简单来说是本身可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进 ...
- Python基础知识-09-函数
python其他知识目录 1.函数介绍 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如pr ...
- 使用Node.js 搭建http服务器 http-server 模块
1. 安装 http-server 模块 npm install http-server -g 全局安装 2.在需要的文件夹 启动 http-server 默认的端口是8080 可以使 ...
- npm 常用指令
npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...
- PSP阶段和WBS
项目:PSP Daily 详情请见项目功能说明书 PSP2.1 Personal Software Process Stages 预估耗时长 Planning 计划 · Estimate · 开发 ...
- AVL树 算法思想与代码实现
AVL树是高度平衡的二叉搜索树,按照二叉搜索树(Binary Search Tree)的性质,AVL首先要满足: 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不为空, ...
- listagg wm_concat 行转列
一. 这个写法和wm_concat相似,listagg(day,',')要把哪一列转换为同一行within group (order by day)同一行如何排序 with temp as ( ' d ...
- 四则运算——单元测试(测试方法:Right-BICEP )
一.测试的具体部位 Right-结果是否正确? B-是否所有的边界条件都是正确的? I-能查一下反向关联吗? C-能用其他手段交叉检查一下结果吗? E-你是否可以强制错误条件发生? P-是否满足性能要 ...