Keywords Search HDU2222 AC自动机模板题
ac自动机说起来很复杂,其实和kmp是一样的思路,都是寻找相同前后缀,减少跳的次数。只要理解了kmp是怎么求next数组的,ac自动机bfs甚至比knp还好写。
这里大致说一下kmp求next数组的方法吧,假设现在要求第c个字符的next值(假设这个c很大,这样画图出来比较清晰方便理解),因为遍历过程中我们已经知道了第c-1个字符的next为x(假设比c小很多),即next[c-1] = x。那就代表我们知道了a[1]—a[x]这一段和a[c-1-x]—a[c-1]这一段是相等的对吧。
那么现在有两种情况
一。a[x+1] 和 a[c]相等,那么显然变成了a[1]—a[x+1] 这一段和a[c-1-x]—a[c]这一段相等,即c位置的相同前后缀长度比c-1多了1,就是next[c-1]+1;
即原来是:
1——————————x == c-1-x ————————————————c-1 ① 由于a[x+1] == a[c],变成了
1——————————x+1 == c-1-x——————————————————c
二。如果不相等,那么我们在1——x这一段下功夫,假设next[x] = y,即1——y == x-y——x这两段相等,注意根据①式,x-y——x == c-1-y——c-1,画个图就很清楚了,所以如果a[y+1] == a[c],那么相同前后缀长度就是y+1了。
即因为
1——————————x == c-1-x————————————————c-1
1——y == x-y———x == c-1-x——c-1-x+y == c-1-y————c-1 由于a[y+1] == a[c],变成了
1——y+1 == c-1-y——————c
那如果a[y+1] 与a[c]还是不相等怎么办?其实细心的话应该发现这是一个递归过程了——只要再找next[y],循环上面的过程就可以了,想明白这个过程再去看求next数组的代码就很容易理解了。
最后还是上这道题代码:
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <set>
#include <stack>
#include <math.h>
#include <string>
#include <algorithm> #define SIGMA_SIZE 26
#define pii pair<int,int>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x&-x)
#define fode(i, a, b) for(int i=a; i>=b; i--)
#define foe(i, a, b) for(int i=a; i<=b; i++)
#define fod(i, a, b) for(int i=a; i>b; i--)
#define fo(i, a, b) for(int i=a; i<b; i++)
//#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL;
inline LL LMax(LL a, LL b) { return a>b ? a : b; }
inline LL LMin(LL a, LL b) { return a>b ? b : a; }
inline LL lgcd(LL a, LL b) { return b == ? a : lgcd(b, a%b); }
inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm
inline int Max(int a, int b) { return a>b ? a : b; }
inline int Min(int a, int b) { return a>b ? b : a; }
inline int gcd(int a, int b) { return b == ? a : gcd(b, a%b); }
inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL lmod = 1e9+;
const int mod = ;
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const int maxk = 1e5+;
const int maxm = *;
const int maxn = 5e5+; struct node {
node *fail, *s[];
int w;
node() {} void init() {
fail = NULL;
fo(i, , ) s[i] = NULL;
w = ;
}
}*head; int n, ans;
char str[];
queue<node*> q; node* getfail(node* p, int x)
{
if (p->s[x] != NULL) return p->s[x];
else {
if (p == head) return head;
else return getfail(p->fail, x);
}
} void build()
{
node* root = head;
node* tmp; int len = strlen(str);
for ( int j = ; j < len; j++ )
{
int k = str[j]-'a';
if (root->s[k] == NULL) {
tmp = new node; tmp->init();
tmp->fail = head;
root->s[k] = tmp;
} root = root->s[k];
//标记单词结尾
if (j == len-) root->w++;
}
} void build_ac()
{
node* r;
while(!q.empty()) q.pop();
q.push(head);
while(!q.empty())
{
r = q.front(); q.pop();
fo(j, , )
{
if (r->s[j] != NULL) {
q.push(r->s[j]);
if (r == head) r->s[j]->fail = head;
else r->s[j]->fail = getfail(r->fail, j);
}
}
}
return;
} void solve()
{
int len = strlen(str);
node *tmp, *r = head;
fo(j, , len)
{
int k = str[j]-'a';
//找到前缀
while( r->s[k]==NULL && r != head ) r = r->fail;
//自动机向下匹配
//如果可以匹配,则进入下一节点,否则返回头节点
r = (r->s[k]==NULL) ? head : r->s[k];
tmp = r; //如果单词a出现,则他的前缀也全部出现过
while(tmp != head) {
ans += tmp->w;
tmp->w = ;
tmp = tmp->fail;
}
}
return;
} void init()
{
cin >> n; ans = ;
head = new node, head->init();
foe(i, , n)
scanf("%s", str), build(); build_ac();
scanf("%s", str);
} int main()
{ #ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif int t; cin >> t;
while(t--)
{
init();
solve();
printf("%d\n", ans);
} return ;
}
Keywords Search HDU2222 AC自动机模板题的更多相关文章
- HDU-2222 Keywords Search(AC自动机--模板题)
题目大意:统计一共出现了多少次模板串. 题目分析:AC自动机的模板题.不过这题有坑,相同的模板串不能只算一次. 代码如下: # include<iostream> # include< ...
- HDU 2222 Keywords Search(AC自动机模板题)
http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:给出多个单词,最后再给出一个模式串,求在该模式串中包含了多少个单词. 思路: AC自动机的模板题. ...
- hdu_2222: Keywords Search(AC自动机模板题)
题目链接 统计一段字符串中有多少个模板串在里面出现过 #include<bits/stdc++.h> using namespace std; ; struct Trie { ]; int ...
- HDU2222 Keywords Search(AC自动机模板)
AC自动机是一种多模式匹配的算法.大概过程如下: 首先所有模式串构造一棵Trie树,Trie树上的每个非根结点都代表一个从根出发到该点路径的字符串. 然后每个结点都计算出其fail指针的值,这个fai ...
- HDU 2222 Keywords Search(AC自动机模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- HDU 2222 Keywords Search 【AC自动机模板】
询问有多少个模式串出现在了文本串里面.将模式串插入Trie树中,然后跑一边AC自动机统计一下就哦了. 献上一份模板. #include <cstdio> #include <cstr ...
- HDU 2222:Keywords Search(AC自动机模板)
http://acm.hdu.edu.cn/showproblem.php?pid=2222 KMP是单模式串匹配的算法,而AC自动机是用于多模式串匹配的算法.主要由Trie和KMP的思想构成. 题意 ...
- HDU 2222 AC自动机模板题
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...
- HDU 3065 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...
随机推荐
- 让nginx支持patchinfo,(支持codeigniter,thinkphp,ZF等框架)
nginx 的config配置: server { listen ; server_name xxx; ....if (!-e $request_filename) { rewrite ^/(.*)$ ...
- csp-s模拟测试97
csp-s模拟测试97 猿型毕露.水题一眼秒,火题切不动,还是太菜了. $T1$看了一会儿感觉$woc$期望题$T1??$假的吧??. $T2$秒. $T3$什么玩意儿. 40 01:24:46 00 ...
- [JZOJ 5852] 相交
题意:求树上两条路径有无祖先. 思路: 瞎搞\(LCA\)啊... 可惜我\(LCA\)打错了,我居然调了半小时...qwq #include <bits/stdc++.h> using ...
- SPSS单一样本的T检验
SPSS单一样本的T检验 如果已知总体均数,进行样本均数与总体均数之间的差异显著性检验属于单一样本的T检验.在SPSS中,单一样本的T检验由"One-Sample T Test"过 ...
- Codeforces 1174B Ehab Is an Odd Person
题目链接:http://codeforces.com/problemset/problem/1174/B 题意:给定长度 n 的数组,任意俩个相加为奇数的数可以交换数组中的位置,让这个数组尽量从小到大 ...
- docker 使用网络以及容器互联
[root@docker01 /]# docker run -d -p : --name web training/webapp ####小p ,容器的5000端口随机映射到宿主机的9999端口 se ...
- 大神给你分析HTTPS和HTTP的区别
今天在做雅虎的时候,发现用第三方工具截取不到客户端与服务端的通讯,以前重来没碰到过这种情况,仔细看了看,它的url请求时基于https的,gg了下发现原来https协议和http有着很大的区别.总的来 ...
- 大道浮屠诀---cwRsync同步工具的使用
目的: 在日常生活中,我们有时候会遇到这样类似的问题 ---需要把一台服务器上的某个重要的文件进行备份(拷贝另外的服务器上) ---需要同步系统上的配置文件到其他系统 利用此cwRsync软件可以解决 ...
- ASP.NET Core Web应用在发布时选择是否对视图进行编译
原文:ASP.NET Core Web应用在发布时选择是否对视图进行编译 在我们发布ASP.NET Core Web应用程序时,选择以文件形式发布,发布方法选择文件系统 默认情况下,会把Views的视 ...
- Xcode常见路径
模拟器安装的位置: /Library/Developer/CoreSimulator/Profiles/Runtimes 可以通过Xcode安装 模拟器程序的沙盒 Xcode编译生成的Product ...