您的位置:首页 > 其它

Hdu 5384 Danganronpa (AC自动机模板)

2015-08-14 15:42 302 查看
题目链接:

  Hdu 5384 Danganronpa

题目描述:

  给出n个目标串Ai,m个模式串Bj,问每个目标串中m个模式串出现的次数总和为多少?

解题思路:

  与Hdu 2222 Keywords Search十分相似,hdu2222求目标串中包含几个模式串,本题目求模式串在目标串中出现了几次(比赛的时候模板都不会就悲剧了┭┮﹏┭┮)

  初学AC自动机可以参考大神博客,总结的真的炒鸡棒讷。涨姿势请点击下面尊贵的链接大人:

  AC自动机算法总结 AC自动机模板

  学完AC自动机就可以套模板解决这个站在冰柜上的高冷题目了~~~~.

  对所有的Bj建立Trie图,然后在Trie的基础上建立fail数组,在fail数组上每遇到一个Bj的终点,都会对计算结果有1的贡献。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 100005;
const int maxm = 10005;
char A[maxn][maxm], B[maxm];

struct Trie
{
int next[maxn][26], fail[maxn], end[maxn];
int L, root;

int newnode ()
{
for (int i=0; i<26; i++)
next[L][i] = -1;
end[L] = 0;
return L++;
}

void init ()
{
L = 0;
root = newnode();
}

void insert (char s[])
{
int now = root;
for (int i=0; s[i]; i++)
{
if (next[now][s[i]-'a'] == -1)
next[now][s[i]-'a'] = newnode();
now = next[now][s[i]-'a'];
}
end[now] ++;
}

void build ()
{
queue <int> Q;
fail[root] = root;
for (int i=0; i<26; i++)
if (next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty())
{
int now = Q.front();
Q.pop ();
for (int i=0; i<26; i++)
{
if (next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push (next[now][i]);
}
}
}
}

int query (char s[])
{
int now = root, res = 0;
for (int i=0; s[i]; i++)
{
now = next[now][s[i] - 'a'];
int temp = now;
while (temp != root)
{
res += end[temp];
temp = fail[temp];
}
}
return res;
}
}ac;

int main ()
{
int t, n, m;
scanf ("%d", &t);

while (t --)
{
ac.init ();
scanf ("%d %d", &n, &m);
for (int i=0; i<n; i++)
scanf ("%s", A[i]);

for (int i=0; i<m; i++)
{
scanf ("%s", B);
ac.insert (B);
}

ac.build ();
for (int i=0; i<n; i++)
{
int res = ac.query(A[i]);
printf ("%d\n", res);
}

}

return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: