[AC自动机+dp+高精度] poj 1625 Censored!

题意:

给一个长度为N的字符串,表示有N个字符可用。

再给p个不能含有的病毒串。

为你长度为M的串不含有任意一个病毒串的方案数。

思路:

由于不需要取模,50^50需要用到高精度。

因为题目的字符串大于32所以可以直接scanf输入。

输入完map一下就好了。

就是裸的自动机dp了。

代码:

#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"iostream"
#include"queue"
#include"map"
#include"string"
#define mod 998244353
#define ll long long
using namespace std;
map<char,int>mp;
struct trie
{
    int mark,id;
    trie *next[55],*fail;
    trie()
    {
        memset(next,0,sizeof(next));
        fail=NULL;
        mark=0;
    }
};
trie *node[1000],*root;
int triecont,n;
void init(char *v)
{
    trie *p=root;
    for(int i=0;v[i]!='\0';i++)
    {
        int tep=mp[v[i]];
        if(p->next[tep]==NULL)
        {
            p->next[tep]=new trie();
            p->next[tep]->id=triecont;
            node[triecont++]=p->next[tep];
        }
        p=p->next[tep];
    }
    p->mark=1;
}
void getac()
{
    queue<trie*>q;
    q.push(root);
    while(!q.empty())
    {
        trie *p=q.front();
        q.pop();
        for(int i=0;i<n;i++)
        {
            if(p->next[i]==NULL)
            {
                if(p==root) p->next[i]=root;
                else p->next[i]=p->fail->next[i];
            }
            else
            {
                if(p==root) p->next[i]->fail=root;
                else p->next[i]->fail=p->fail->next[i];
                q.push(p->next[i]);
                if( p!=root && p->fail->next[i]->mark==1) p->next[i]->mark=1;
            }
        }
    }
}
int dp[55][123][123];
int main()
{
    int m,p;
    while(scanf("%d%d%d",&n,&m,&p)!=-1)
    {
        triecont=0;
        root=new trie();
        root->id=triecont;
        node[triecont++]=root;
        mp.clear();
        char x[123];
        getchar();
        gets(x);
        for(int i=0;i<n;i++) mp[x[i]]=i;
        for(int i=0;i<p;i++)
        {
            gets(x);
            init(x);
        }
        getac();
        memset(dp,0,sizeof(dp));
        dp[0][0][100]=1;
        for(int i=1;i<=m;i++)
        {
            for(int j=0;j<triecont;j++)
            {
                for(int k=0;k<n;k++)
                {
                    trie *p=node[j]->next[k];
                    if(p->mark==1) continue;
                    for(int l=100;l>=1;l--) dp[i][p->id][l]+=dp[i-1][j][l];
                    for(int l=100;l>=1;l--)
                    {
                        if(dp[i][p->id][l]>9)
                        {
                            dp[i][p->id][l-1]+=dp[i][p->id][l]/10;
                            dp[i][p->id][l]%=10;
                        }
                    }
                }
            }
        }

        int ans[123];
        memset(ans,0,sizeof(ans));
        for(int i=0;i<triecont;i++)
        {
            for(int j=100;j>=1;j--) ans[j]+=dp[m][i][j];
            for(int j=100;j>=1;j--)
            {
                if(ans[j]>9)
                {
                    ans[j-1]+=ans[j]/10;
                    ans[j]%=10;
                }
            }
        }
        int j;
        for(j=0;j<=100;j++) if(ans[j]) break;
        if(j==101) puts("0");
        else
        {
            for(j=j;j<=100;j++) printf("%d",ans[j]);
            puts("");
        }
    }
    return 0;
}
时间: 2024-11-06 07:53:30

[AC自动机+dp+高精度] poj 1625 Censored!的相关文章

poj 1625 Censored!(AC自动机+DP+高精度)

题目链接:poj 1625 Censored! 题目大意:给定N,M,K,然后给定一个N字符的字符集和,现在要用这些字符组成一个长度为M的字符串,要求不包 括K个子字符串. 解题思路:AC自动机+DP+高精度.这题恶心的要死,给定的不能匹配字符串里面有负数的字符情况,也算是涨姿势 了,对应每个字符固定偏移128单位. #include <cstdio> #include <cstring> #include <queue> #include <vector>

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

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&

poj 1625 Censored!

Censored! http://poj.org/problem?id=1625 Time Limit: 5000MS   Memory Limit: 10000K       Description The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters witho

HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp)

HDU 2243 考研路茫茫――单词情结 题意:给定一些词根,如果一个单词包含有词根,则认为是有效的.现在问长度不超过L的单词里面,有多少有效的单词? 思路:这道题和POJ 2778是同样的思路.POJ 2778是要找出长度为L的单词里面有多少无效的单词.那么根据同样的方法构造矩阵,然后所有无效的单词个数为 A + A^2 + ... + A^l 个.而所有单词的个数为26 + 26^2 + - + 26^l 个.两个减一下即为答案. 矩阵连乘求和:I + A^2 + A^3 + ... + A

HDU3341 Lost&#39;s revenge(AC自动机+DP)

题目是给一个DNA重新排列使其包含最多的数论基因. 考虑到内存大概就只能这么表示状态: dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数 其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个. 接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值. 这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也

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

HDU2296——Ring(AC自动机+DP)

题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小的. 题解:AC自动机+dp.dp[i][j]表示在字符串长度i,在自动机的第j个状态.因为要字典序最小,所以转移时要保持字典序最小. 想了各种转移姿势 最后还是查了题解 发现可以直接记录前缀转移…… #include <bits/stdc++.h> using namespace std; co

hdu 2296 aC自动机+dp(得到价值最大的字符串)

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