HDU 5384 Danganronpa(AC自动机)

Danganronpa

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 429    Accepted Submission(s): 248

Problem Description

Danganronpa is a video game franchise created and developed by Spike Chunsoft, the series‘ name is compounded from the Japanese words for "bullet" (dangan) and "refutation" (ronpa).

Now, Stilwell is playing this game. There are n verbal
evidences, and Stilwell has m "bullets".
Stilwell will use these bullets to shoot every verbal evidence.

Verbal evidences will be described as some strings Ai,
and bullets are some strings Bj.
The damage to verbal evidence Ai from
the bullet Bj is f(Ai,Bj).

f(A,B)=∑i=1|A|?|B|+1[ A[i...i+|B|?1]=B ]

In other words, f(A,B) is
equal to the times that string B appears
as a substring in string A.

For example: f(ababa,ab)=2, f(ccccc,cc)=4

Stilwell wants to calculate the total damage of each verbal evidence Ai after
shooting all m bullets Bj,
in other words is ∑mj=1f(Ai,Bj).

Input

The first line of the input contains a single number T,
the number of test cases.

For each test case, the first line contains two integers n, m.

Next n lines,
each line contains a string Ai,
describing a verbal evidence.

Next m lines,
each line contains a string Bj,
describing a bullet.

T≤10

For each test case, n,m≤105, 1≤|Ai|,|Bj|≤104, ∑|Ai|≤105, ∑|Bj|≤105

For all test case, ∑|Ai|≤6?105, ∑|Bj|≤6?105, Ai and Bj consist
of only lowercase English letters

Output

For each test case, output n lines,
each line contains a integer describing the total damage of Ai from
all m bullets, ∑mj=1f(Ai,Bj).

Sample Input

1
5 6
orz
sto
kirigiri
danganronpa
ooooo
o
kyouko
dangan
ronpa
ooooo
ooooo

Sample Output

1
1
0
3
7

Author

SXYZ

Source

2015 Multi-University Training Contest 8

题意:给n个母串,给m个匹配串,求每个母串依次和匹配串匹配,能得到的数目和。

题解:AC自动机模板题

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
struct Trie {
    int next[500010][26],fail[500010],end[500010];
    int root,L;
    int newnode() {
        for(int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L-1;
    }
    void init() {
        L = 0;
        root = newnode();
    }
    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++) {
            if(next[now][buf[i]-'a'] == -1)
                next[now][buf[i]-'a'] = newnode();
            now = next[now][buf[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 buf[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for(int i = 0; i < len; i++) {
            now = next[now][buf[i]-'a'];
            int temp = now;
            while( temp != root ) {
                res += end[temp];
                //end[temp] = 0;
                temp = fail[temp];
            }
        }
        return res;
    }
    void debug() {
        for(int i = 0; i < L; i++) {
            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
            for(int j = 0; j < 26; j++)
                printf("%2d",next[i][j]);
            printf("]\n");
        }
    }
};
char buf[100010];
int m;
char s[605015];
char c[10010];
Trie ac;
int main() {
   // freopen("test.in","r",stdin);
    int T;
    int n;
    scanf("%d",&T);
    while( T-- ) {
        scanf("%d%d",&n,&m);
        ac.init();
        memset(s,0,sizeof s);
        int len=0;
        for(int i=0; i<n; i++) { ///把所有的串接起来,用空格隔开
            scanf("%s",c);
            int l=strlen(c);
            if(i!=0)s[len++]=' ';
            strcat(s,c);
            len+=l;
        }
        s[len]=' ';
        s[++len]=0;
        for(int i=0; i<m; i++) {
            scanf("%s",buf);
            ac.insert(buf);
        }
        ac.build();
        int l=0;
        while(l<len) {
            int k=0;
            while(s[l]!=' ') {///找到当前单词
                buf[k++]=s[l++];
            }
            buf[k]=0;
            l++;
            printf("%d\n",ac.query(buf));
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-06 19:50:45

HDU 5384 Danganronpa(AC自动机)的相关文章

HDU 5384——Danganronpa——————【AC自动机】

Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 582    Accepted Submission(s): 323 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft

hdu 5384 Danganronpa(基础AC自动机)

题意:多个模式串和多个待匹配串,求每个待匹配串对于所有模式串的匹配个数: 思路:1.与最裸的ac自动机的区别在于讯问后的叶子节点的count值会改变,在每次询问时count值不要清零: 2.对于多个串的保存直接用二维数组: #include<cstdio> #include<vector> #include<iostream> #include<algorithm> #include<cstring> using namespace std; c

HDU 5384 Danganronpa (字典树运用)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5384 题面: Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 512    Accepted Submission(s): 284 Problem Description Danganronpa is a vid

HDU 2222(AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题思路: AC自动机模板题. 一开始使用LRJ的坑爹静态模板,不支持重复的模式串. 在做AC自动机+DP的时候,扒了zcwwzdjn大神的动态优化(失配指向root)写法,以及借鉴了网上的AC自动机模板, 搞出了这么一个支持重复串的模板. #include "cstdio" #include

hdu5384 Danganronpa(AC自动机)

题目: Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 827    Accepted Submission(s): 443 Problem Description Danganronpa is a video game franchise created and developed by Spike Chu

2017多校第6场 HDU 6096 String AC自动机

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: 因为要求前缀后缀都包含的个数,所以可以把字符串a转换成a#a这样一个字符串,比如abca就转换成abca#abca 然后对于一组前缀a后缀b转换成b{a,比如ab ca,就是ca{ab, 然后对前缀后缀的串建立AC自动机,让主串去匹配,如上述例子,ca{ab满足为abca{abca的一个子串,也就

HDU 2296 Ring [AC自动机 DP 打印方案]

Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3536 Accepted Submission(s): 1153 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic

HDU 2296 Ring AC自动机 + DP

题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串来辅助二维DP(新思路) , DP[i][j] ,表示到i位置状态为j的最大得分. 解题代码: 1 // File Name: temp.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月11日 星期四 15时18分4秒 4 5 #inclu

HDU 6096 String (AC自动机)

题意:给出n个字符串和q个询问,每次询问给出两个串 p 和 s .要求统计所有字符串中前缀为 p 且后缀为 s (不可重叠)的字符串的数量. 析:真是觉得没有思路啊,看了官方题解,真是好复杂. 假设原始的字符串 数组为A,首先将A中的每个字符串都进行翻转,得到字符串数组B,然后,将A和B按字典序排序. 对于一个查询来说有一个前缀p和后缀s, 所有包含前缀p的字符串在A中是连续的,可通过二分求出该区间 设为[Lp,Rp],同样,所有包含后缀s的字符串在B中也是连续的,设为[Ls,Rs] 接下来只需