计蒜客习题:猴子打字


问题描述

有一个有趣的定理:无限猴子定理(infinite monkey theorem),它的表述如下:让一只猴子在打字机上随机按键,当按键次数达到无穷时,几乎必然能够打出任何给定的文字。
给出一篇猴子打出的“文章”,并给定一个由若干个词组成的词典,问猴子一共打出了多少个在词典中出现的词。
输入格式
第一行一个整数 n(1≤n≤10000),表示词典中单词的个数。
接下来 n 行,每行一个仅由小写字母组成的单词,长度不超过 50。
最后一行是一篇仅由小写字母组成的文章,长度不超过 1000000。
输出格式
一行一个整数,表示答案。
样例输入
5
jsk
jisuan
suantou
love
program
jisuantouisprogramming
样例输出
3


AC代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1000005
#define maxm 1000005
using namespace std;
int n,tot,head,tail,son[maxm][26],fai[maxm],sum[maxm],list[maxm];
char s[maxn];
void clear(){
        tot=0;
        memset(son,0,sizeof(son));
        memset(sum,0,sizeof(sum));
    }
    void insert(char *s){
        int p=0;
        for (int i=1;s[i];p=son[p][s[i]-'a'],i++) if (!son[p][s[i]-'a']) son[p][s[i]-'a']=++tot;
        sum[p]++;
    }
    void failed(){
        head=0,tail=1,list[1]=0,fai[0]=-1;
        while (head!=tail){
            int x=list[++head];
            for (int ch=0;ch<26;ch++)
                if (son[x][ch]){
                    list[++tail]=son[x][ch];
                    int p=fai[x];
                    while (p!=-1&&!son[p][ch]) p=fai[p];
                    if (p==-1) fai[son[x][ch]]=0;
                    else fai[son[x][ch]]=son[p][ch];
                }   
        }
    }
    void work(char *s){
        int ans=0;
        for (int i=1,p=0;s[i];i++){
            while (p&&!son[p][s[i]-'a']) p=fai[p];
            p=son[p][s[i]-'a'];
            for (int t=p;t;t=fai[t]) ans+=sum[t],sum[t]=0;
        }
        printf("%d\n",ans);
    }
int main()
{
        cin>>n;
        for (int i=1;i<=n;i++) scanf("%s",s+1),insert(s);
        failed();
        scanf("%s",s+1),work(s);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80628181
今日推荐