本题是在text里面查找key word的增强版。由于这里有多个text。

那么就不能够简单把Trie的叶子标志记录改动成-1进行加速了,能够使用其它技术。我直接使用个vis数组记录已经訪问过的节点,达到加速效果,速度还算挺快的。

只是看discuss里面有人直接使用Trie,做出了140ms的速度,并且他的程序严格来说并不对。可见本题的数据非常水啊。Trie的时间效率肯定比AC自己主动机低,可是在数据非常水的特殊情况下。Trie的速度也能够非常快的。

注意两个细节:

1 病毒也须要安装顺序输出,不小心就遗漏了。这里害我错了几次。

2 还有就是题目的字符不确定是多少。使用33-94范围的字符測试答案正确的。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
const int MAX_N = 501;
const int MAX_WORD = 201;
const int MAX_M = 1001;
const int MAX_TXT = 10001;
const int MAX_V = 3;
const int ARR_SIZE = 94;
char virus[MAX_WORD], web[MAX_TXT];
int webNum[MAX_V];
int M, N; inline int getIndex(char ch) { return ch - 33; } struct Node
{
int n, num, id;
Node *fail;
Node *arr[ARR_SIZE];
}; void clearNode(Node *rt)
{
rt->n = 0;
rt->num = 0;
rt->id = 0;
rt->fail = NULL;
for (int i = 0; i < ARR_SIZE; i++)
{
rt->arr[i] = NULL;
}
} Node gPool[MAX_N*MAX_WORD], *Trie;
int gPoolID;
bool vis[MAX_N*MAX_WORD]; //怎么老是忘记使用visited技术的? void insertTrie(char *virus, int num)
{
Node *pCrawl = Trie;
for (; *virus; virus++)
{
int id = getIndex(*virus);
if (!pCrawl->arr[id])
{
pCrawl->arr[id] = &gPool[gPoolID++];
clearNode(pCrawl->arr[id]);
pCrawl->arr[id]->id = gPoolID-1;
}
pCrawl = pCrawl->arr[id];
}
pCrawl->n++;
pCrawl->num = num;
} void buildFail()
{
queue<Node *> qu;
qu.push(Trie);
while (!qu.empty())
{
Node *p = qu.front(); qu.pop();
for (int i = 0; i < ARR_SIZE; i++)
{
if (!p->arr[i]) continue;
p->arr[i]->fail = Trie;
Node *fail = p->fail;
while (fail)
{
if (fail->arr[i])
{
p->arr[i]->fail = fail->arr[i];
break;
}
fail = fail->fail;
}
qu.push(p->arr[i]);
}
}
} int searchVirus(char *web)
{
int n = 0;
Node *pCrawl = Trie;
memset(vis, 0, sizeof(bool)*(gPoolID+1));
for (; *web; web++)
{
int i = getIndex(*web);
while (!pCrawl->arr[i] && pCrawl != Trie) pCrawl = pCrawl->fail;
if (pCrawl->arr[i])
{
pCrawl = pCrawl->arr[i];
Node *p = pCrawl;
while (p && !vis[p->id])//使用vis比直接检查数组值快捷方便
{
if (p->n) webNum[n++] = p->num;
vis[p->id] = true;
p = p->fail;
}
if (n == MAX_V) break; //At most MAX_V virus one web
}
}
return n;
} int main()
{
Trie = &gPool[0];
while (scanf("%d", &N) != EOF)
{
gPoolID = 1;
clearNode(Trie);
getchar();
for (int i = 1; i <= N; i++)
{
gets(virus);
insertTrie(virus, i);
}
buildFail(); scanf("%d", &M);
getchar();
int cnt = 0;
for (int i = 1; i <= M; i++)
{
gets(web);
int n = searchVirus(web);
if (n)
{
cnt++;
printf("web %d:", i); sort(webNum, webNum + n);//Watch out: order!
for (int j = 0; j < n; j++)
{
printf(" %d", webNum[j]);
}
putchar('\n');
}
}
printf("total: %d\n", cnt);
}
return 0;
}

HDU 2896 病毒侵袭 AC自己主动机题解的更多相关文章

  1. HDU 2896 病毒侵袭 (AC自己主动机)

    pid=2896">http://acm.hdu.edu.cn/showproblem.php?pid=2896 病毒侵袭 Time Limit: 2000/1000 MS (Java ...

  2. hdu 2896 病毒侵袭 ac自动机

    /* hdu 2896 病毒侵袭 ac自动机 从题意得知,模式串中没有重复的串出现,所以结构体中可以将last[](后缀链接)数组去掉 last[]数组主要是记录具有相同后缀模式串的末尾节点编号 .本 ...

  3. hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. hdu 2896 病毒侵袭 AC自动机 基础题

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  5. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  6. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  7. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  8. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  9. HDU 2222 Keywords Search AC自己主动机入门题

    单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自己主动机的基础: 1 Trie. 以这个数据结构为基础的,只是添加一个fail指针和构造fail的函数 2 KM ...

随机推荐

  1. Unqualified name lookup

    Unqualified name lookup File scope Namespace scope For an qualified name, that is a name that does n ...

  2. JBPM6教程

    JBPM6教程-手把手教你安装JBPM 1. 安装JBPM的先决条件: (1)JDK 1.6+以上,没有安装的话,猛击这里. (2)Ant 1.7+以上,没有安装的话,看看这里. 2. 下载JBPM安 ...

  3. Python学习之路——字符处理(一)

    一.整数: 例如:1.10.30 整数可以做以下操作: bit_length函数:返回该整数占用的最少位数: >>> x=100 >>> x.bit_length( ...

  4. spoj 3871 gcd extreme

    题目大意给出一个n,求sum(gcd(i,j),<i<j<=n); 可以明显的看出来s[n]=s[n-]+f[n]; f[n]=sum(gcd(i,n),<i<n); 现 ...

  5. iOS 数据库第三方FMDB的简单使用

    一 FMDB的简单说明及介绍 FMDB的github地址 https://github.com/ccgus/fmdb FMDB是一款简洁的,易用的封装库,简单介绍一下FMDB的使用 在FMDB下载文件 ...

  6. 文本图片自适应高度小bug以及解决办法

    自定义cell的文本图片自适应高度代码,如果存在自定义的cell赋值封装,就必须将自适应高度代码写在这个方法中 点击效果: 注:- (void)layoutSubviews 方法不能同时操作,否则会出 ...

  7. kinit manual

    Name kinit - obtain and cache Kerberos ticket-granting ticket Synopsis kinit [-V] [-l lifetime] [-s  ...

  8. PDO--PHP Data Objects

    PDO的环境配置:开启支持PDO 在php.ini配置文件里开启: extension=php_pdo.dll extension=php_pdo_mysql.dll 在PDO操作中涉及到类:PDO. ...

  9. if语句求三个数中最大的

    Console.WriteLine("请输入第一个数:"); int a = Convert.ToInt32( Console.ReadLine()); Console.Write ...

  10. ubuntu中在线升级python

    sudo add-apt-repository ppa:fkrull/deadsnakes-python2.7 sudo apt-get update sudo apt-get upgrade 笔记