码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5384 Danganronpa(AC自动机)

时间:2015-08-29 06:24:49      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:acm   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 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.

T10
For each test case, n,m105, 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
 

Recommend
wange2014
 

题意:字符串匹配,多个模式串匹配源串。

思路:AC自动机模板题。

代码:

//AC 自动机
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
inline int Max(int a,int b)
{
    return a>b?a:b;
}
inline int Min(int a,int b)
{
    return a>b?b:a;
}
#define maxnode 600010
#define sigma_size 26

struct Trie
{
    int ch[maxnode][sigma_size];//下一指针
    int val[maxnode];//匹配进度
    int haha[maxnode];//节点i的成功匹配数
    int f[maxnode];//失配指针
    int sz;//size
	//初始化
    void init()
    {
        sz=1;
        memset(ch,0,sizeof(ch));
        memset(val, 0, sizeof(val));
        memset(f,0,sizeof(f));
        memset(haha,0,sizeof(haha));
    }
	//字符 c 的 index
    int idx(char c)
    {
        return c-'a';
    }
	//插入串 s
    int insert(char *s)
    {
		//
        int u = 0, len = strlen(s);
        for(int i = 0; i < len; i++)
        {
			//获取index
            int c = idx(s[i]);
            if(!ch[u][c]) ch[u][c] = sz++;//无路则建立指针到最后一个节点
            u = ch[u][c];//到下一节点
        }
        val[u] ++; //将串结束的位置的val++
        return u;  //返回串S 结束位置的指针
    }
	//计算失败指针
    void getFail()
    {

        queue<int> q;
        for(int i = 0; i<sigma_size; i++)
            if(ch[0][i]) q.push(ch[0][i]);//处理根节点
		//将根节点的所有下一节点加入队列
        while(!q.empty())
        {
            int r = q.front();
            q.pop();
			//取队首为r
			//遍历r的所有下级
            for(int c = 0; c<sigma_size; c++)
            {
                int u = ch[r][c];
                if(!u)continue;//如果下一节点是根节点,跳过
				//将r的下级加入队列
                q.push(u);

                int v = f[r];
                ///沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
				while(v && ch[v][c] == 0) v = f[v];
				f[u] = ch[v][c];//改变失配指针
            }
        }
    }
	//匹配 串T
    void find(char *T)
    {
        int len = strlen(T), j = 0;//j为当前节点编号(0代表根节点)
        for(int i = 0; i < len; i++)
        {
            int c = idx(T[i]);
            while(j && ch[j][c]==0) //当j不是根节点且j到c无路(失配)
				j = f[j];//走失配指针到下一节点(回滚)
			//循环结束时:
			//j 为根节点 或 j到c有路(可配)
            j = ch[j][c];//j到下一节点,若j为根节点且没有路,则j还会走到根节点
            int temp = j;
			//标记整个路上的
            while(temp)//当temp不是根
            {
                haha[temp]++;//在temp节点的进度+1
                temp = f[temp];//回退到失败后节点
            }
        }
    }
};

Trie ac;
char P[100011][10010];
int ans[100010];
char S1[100010];
int main()
{
    int t,m,n;
    scanf("%d",&t);
    while(t--)
    {
        ac.init();
        scanf("%d%d",&m,&n);
        for(int i = 1; i <= m; i++)
        {
            scanf("%s",P[i]);
        }
        for(int i = 1; i <= n; i++)
        {
            scanf("%s",S1);
            ans[i] = ac.insert(S1);
        }
        ac.getFail();
        for(int i = 1; i <= m; i++)
        {
            memset(ac.haha,0,sizeof(ac.haha));
            ac.find(P[i]);
            int sum = 0;
            for(int i=1; i <= n; i++)
                sum += ac.haha[ans[i]];
            printf("%d\n",sum);
        }
    }
    return 0;
}


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

hdu5384 Danganronpa(AC自动机)

标签:acm   ac自动机   

原文地址:http://blog.csdn.net/u013840081/article/details/48070739

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!