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的更多相关文章

  1. poj4052

    题意:求一个文章(长度5.1e6)里面出现了多少个指定的模式串.重复出现只记一次.而且如果两个模式串都出现的情况下,一个是另一个的子串,则该子串不算出现过. 分析:AC自动机. 由于子串不算所以加一些 ...

  2. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

随机推荐

  1. 该用哪个:Redis与Memcached之间如何选择呢?

    华为云分布式缓存Redis5.0和Memcached都是华为云DCS的核心产品. 那么在不同的使用场景之下,如何选择Redis5.0和Memcached呢? 就由小编为大家进行详细的数据对比分析吧 R ...

  2. xshell—实现Linux与Windows之间的文件传递

    在Windows系统上,通过xshell连接Linux系统. 第一种使用方式:从Linux系统上下载文件到Windows系统. 准备工作: $ sudo apt-get install lrzsz 安 ...

  3. 75.[LeetCode] Sort Colors

    Given an array with n objects colored red, white or blue, sort them in-place so that objects of the ...

  4. iPhone上的CPU架构,核数以及运行内存

    机型 CPU架构 CPU名 CPU位数 CPU核数 运行内存 iPhone 5 ARMv7s A6 32bit 双核 1G iPhone 5c ARMV7s A6 32bit 双核 1G iPhone ...

  5. Python学习之路8 - 内置方法

    abs(-230) #取绝对值 all([0,1,-5]) #如果参数里面的所有值都为真就返回真,否则返回假 any([0,1,-5]) #如果参数里面有一个值为真则返回真,否则返回假 ascii([ ...

  6. pandas中DataFrame的ix,loc,iloc索引方式的异同

    pandas中DataFrame的ix,loc,iloc索引方式的异同 1.loc: 按照标签索引,范围包括start和end 2.iloc: 在位置上进行索引,不包括end 3.ix: 先在inde ...

  7. 使用java中的注解@see

    缘起 在写java时,有时需要写注释,而为了更好的描述,需要引用和参考其他代码.为了让阅读者更好的体验,javadoc中支持链接跳转,这就需要用到注解@see. @see用法 注解@see可以在注释中 ...

  8. playbook详解—YAML格式的文本

    在playbook中有一些核心的指令 hosts:指明命令运行在哪个node之上 remote_user:在远端的node之上以什么用户的身份运行命令 var:给模板传递变量值 tasks:指明需要执 ...

  9. arp请求与回复

    实验环境:wifi 1,手机192.168.1.103 2,电脑192.168.1.106 先删除电脑arp表数据 ping request: reply:

  10. QList和QVector使用

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QList和QVector使用     本文地址:http://techieliang.com ...