poj1625 ac自动机

Censored!

Time Limit: 5000MS   Memory Limit: 10000K
Total Submissions: 8102   Accepted: 2191

Description

The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters without word breaks. So, there exist exactly N^M different Freish sentences.

But after recent election of Mr. Grass Jr. as Freeland president some words offending him were declared unprintable and all sentences containing at least one of them were forbidden. The sentence S contains a word W if W is a substring of S i.e. exists such k >= 1 that S[k] = W[1], S[k+1] = W[2], ...,S[k+len(W)-1] = W[len(W)], where k+len(W)-1 <= M and len(W) denotes length of W. Everyone who uses a forbidden sentence is to be put to jail for 10 years.

Find out how many different sentences can be used now by freelanders without risk to be put to jail for using it.

Input

The first line of the input file contains three integer numbers: N -- the number of letters in Freish alphabet, M -- the length of all Freish sentences and P -- the number of forbidden words (1 <= N <= 50, 1 <= M <= 50, 0 <= P <= 10).

The second line contains exactly N different characters -- the letters of the Freish alphabet (all with ASCII code greater than 32).

The following P lines contain forbidden words, each not longer than min(M, 10) characters, all containing only letters of Freish alphabet.

Output

Output the only integer number -- the number of different sentences freelanders can safely use.

Sample Input

2 3 1
ab
bb

Sample Output

5

在AC自动机上dp,dp[i][j]表示走了i位,在ac自动机上第j个位置的方案数。ans比较大,要用高精度。

据说有些鬼畜的数据。所以不要用s[i]-32,用hash比较好

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;

struct node{
    node *fail;
    node *son[100];
    int num;
    bool ar;
    node()
    {
        fail=NULL;
        ar=true;
        num=0;
        for(int i=0;i<100;i++)son[i]=NULL;
    }
} *que[1011];
node *root;
char s[1011];
int len,n,m,t,i,tot;
node *ac[1011];
struct ans{
    int n;
    int a[101];
}dp[61][601];
ans xzq;
int hash[601];

ans plus(ans a,ans b)
{
    ans c;
    int i;
    for(i=0;i<=100;i++)c.a[i]=0;
    if(a.n>b.n)c.n=a.n;
    else c.n=b.n;
    for(i=1;i<=c.n;i++){
        c.a[i]=c.a[i]+a.a[i]+b.a[i];
        if(c.a[i]>=10){
            c.a[i+1]=c.a[i+1]+c.a[i]/10;
            c.a[i]=c.a[i]%10;
        }
    }
    c.n++;
    if(c.a[c.n]==0)c.n--;
    return c;
}

void Read()
{
    len=0;
    char c;
    while(c=getchar(),c==‘\n‘);
    s[++len]=c;
    while(c=getchar(),c!=‘\n‘)s[++len]=c;
}

void add()
{
    int i,ws;
    node *p;
    p=root;
    for(i=1;i<=len;i++){
        ws=hash[s[i]];
        if(p->son[ws]==NULL){
            p->son[ws]=new node();
            p->son[ws]->num=++tot;
            ac[tot]=p->son[ws];
        }
        p=p->son[ws];
    }
    p->ar=false;
}

void Bfs()
{
    int l,r,i,j,k;
    node *p;
    node *q;
    que[l=r=1]=root;
    while(l<=r){
        p=que[l];
        for(i=1;i<=n;i++)if(p->son[i]!=NULL){
            r++;
            que[r]=p->son[i];
            if(p==root)p->son[i]->fail=root;
            else{
                q=p->fail;
                while(q!=NULL){
                    if(q->son[i]!=NULL){
                        p->son[i]->fail=q->son[i];
                        break;
                    }
                    q=q->fail;
                }
                if(p->son[i]->fail==NULL)p->son[i]->fail=root;
            }
        }
        l++;
    }
    for(i=2;i<=r;i++)que[i]->ar&=que[i]->fail->ar;
}

void Main()
{
    int i,j,k;
    node *p;
    node *q;
    dp[0][1].n=1;
    dp[0][1].a[1]=1;
    for(i=0;i<m;i++){
        for(j=1;j<=tot;j++){
            for(k=1;k<=n;k++){
                p=ac[j];
                if(p->son[k]!=NULL)p=p->son[k];
                else{
                    q=p->fail;
                    while(q!=NULL){
                        if(q->son[k]!=NULL){
                            p=q->son[k];
                            break;
                        }
                        q=q->fail;
                    }
                    if(q==NULL)p=root;
                }
                if(p->ar==true)dp[i+1][p->num]=plus(dp[i+1][p->num],dp[i][j]);
            }
        }
    }
    for(i=1;i<=tot;i++)xzq=plus(xzq,dp[m][i]);
}

int main()
{
    tot=0;
    root=new node();
    root->num=++tot;
    ac[tot]=root;
    scanf("%d%d%d",&n,&m,&t);
    Read();
    for(i=1;i<=len;i++)hash[s[i]]=i;
    for(i=1;i<=t;i++){
        Read();
        add();
    }
    Bfs();
    Main();
    if(xzq.n==0)printf("0\n");
    else{
        for(i=xzq.n;i>=1;i--)printf("%d",xzq.a[i]);
        printf("\n");
    }
}
时间: 2024-10-01 05:19:15

poj1625 ac自动机的相关文章

POJ1625 Censored!(AC自动机+DP)

题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后缀状态为自动机第j个结点的合法字符串数 dp[0][0]=1 转移转移... 注意要用高精度,因为答案最多5050. 还有就是要用unsigned char,题目的输入居然有拓展的ASCII码,编码128-255. 1 #include<cstdio> 2 #include<cstring&

POJ1625---Censored!(AC自动机+dp+高精度)

Description The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters without word breaks. So, there exist exactly N^M different Freish sentences. But after recent

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需