题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065

思路分析:问题需要模式匹配多个模式串,需要注意的是模式串会包含和重叠,需要对AC自动机的匹配过程进行修改,对于每个节点,需要从该节点的失败指针回溯,

如果失败指针回溯后的节点为某个模式串的最后一个节点,则匹配了另一个模式串;

代码如下:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int KIND = ;
const int MAX_NODE = * ;
const int MAX_N = + ;
const int MAX_M = + ;
char str[MAX_M];
int visited[MAX_N];
int vir_match[MAX_N];
char vir[MAX_N][]; struct Trie {
int root, count;
int next[MAX_NODE][KIND], fail[MAX_NODE], end[MAX_NODE];
void Init()
{
count = ;
root = NewNode();
}
int NewNode()
{
for (int i = ; i < KIND; ++i)
next[count][i] = -;
end[count] = -;
return count++;
} void Insert(char *str, int id)
{
int i = , k = ;
int now = root; while (str[i])
{
k = str[i];
if (next[now][k] == -)
next[now][k] = NewNode();
now = next[now][k];
++i;
}
end[now] = id;
} void BuildAutomaton()
{
queue<int> Q; fail[root] = -;
Q.push(root);
while (!Q.empty())
{
int now = Q.front();
int p = -;
Q.pop(); for (int i = ; i < KIND; ++i)
{
if (next[now][i] != -)
{
if (now == root)
fail[next[now][i]] = root;
else
{
p = fail[now];
while (p != -)
{
if (next[p][i] != -)
{
fail[next[now][i]] = next[p][i];
break;
}
p = fail[p];
}
if (p == -)
fail[next[now][i]] = root;
}
Q.push(next[now][i]);
}
}
}
} int Match(char *str)
{
int i = , k = , vir_count = ;
int p = root; while (str[i])
{
k = str[i];
while (next[p][k] == - && p != root)
p = fail[p];
p = next[p][k];
p = (p == -) ? root : p; int temp = p;
while (temp != root)
{
if (end[temp] != -)
{
if (visited[end[p]] == )
vir_match[vir_count++] = end[p];
visited[end[p]]++;
}
temp = fail[temp];
}
++i;
}
return vir_count;
}
};
Trie root; int main()
{
int vir_num = ;
int match_count = ; while (scanf("%d\n", &vir_num) != EOF)
{
root.Init();
memset(vir_match, , sizeof(vir_match));
memset(visited, , sizeof(visited));
for (int i = ; i < vir_num; ++i)
{
gets(str);
strcpy(vir[i], str);
root.Insert(str, i + );
} match_count = ;
root.BuildAutomaton();
gets(str);
int ans = root.Match(str);
sort(vir_match, vir_match + ans);
if (ans)
{
for (int j = ; j < ans - ; ++j)
printf("%s: %d\n", vir[vir_match[j] - ], visited[vir_match[j]]);
printf("%s: %d\n", vir[vir_match[ans - ] - ],
visited[vir_match[ans - ]]);
}
}
return ;
}

最新文章

  1. centos 6.5 redis 安装
  2. IP分片重组的分析和常见碎片攻击 v0.2
  3. ffmpeg relocation error
  4. SVN修改用户名与密码
  5. SharpGL学习笔记(十九) 摄像机漫游
  6. hdu 2665 Kth number
  7. sybase下convert函数第三个参数(时间格式)
  8. DropDownList单选与多选下拉框
  9. Solidity教程系列1 - 类型介绍
  10. Java Web高级编程(二)
  11. 构建微服务开发环境8————Hello 微服务
  12. php中连接mysql数据库的第一步操作
  13. 利用httpd配置虚拟目录创建下载站点
  14. 选择J2EE的SSH框架的理由
  15. 高精度减法--C++
  16. 首个threejs项目-前端填坑指南【转】
  17. iOS7.0中UILabel高度调整注意事项
  18. 2018-2019-2 20165209 《网络对抗技术》Exp5:MSF基础应用
  19. js动态生成水印
  20. 24.Semaphore

热门文章

  1. mysql数据库中列转行
  2. codevs 1183 泥泞的道路 01分数规划
  3. 【LeetCode题意分析&amp;解答】34. Search for a Range
  4. Git库文件的状态
  5. Java经典问题算法大全
  6. 跨浏览器resize事件分析
  7. VS2015自定义注释内容
  8. c#学习心得,慢慢添加,如果有错误希望大家留言,我刚开始学
  9. ios开发学习笔记(1)
  10. zoj 1366 Cash Machine