题目:给你n个字母,p个模式串,要你写一个长度为m的串,要求这个串不能包含模式串,问你这样的串最多能写几个

思路:dp+AC自动机应该能看出来,万万没想到这题还要加大数...orz

状态转移方程dp[i + 1][j->next] += dp[i][j],其他思路和上一题hdu2457一样的,就是在AC自动机里跑就行了,不要遇到模式串结尾,然后最后把所有结尾求和就是答案。

注意下题目说给最多给50个字符且ASCII码大于32但是没说多大,直接开100多会RE,这里用map假装离散化一下。

参考:

C++大数模板 BigInteger

代码:

#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 1000+5;
const int maxm = 100000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
const int kind = 55;
const char baset = 0;
using namespace std;

/**********大数模板-start************/
struct BigInteger{
    int A[25];
    enum{MOD = 10000};
    BigInteger(){memset(A, 0, sizeof(A)); A[0]=1;}
    void set(int x){memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
    void print(){
        printf("%d", A[A[0]]);
        for (int i=A[0]-1; i>0; i--){
            if (A[i]==0){printf("0000"); continue;}
            for (int k=10; k*A[i]<MOD; k*=10) printf("0");
            printf("%d", A[i]);
        }
        printf("\n");
    }
    int& operator [] (int p) {return A[p];}
    const int& operator [] (int p) const {return A[p];}
    BigInteger operator + (const BigInteger& B){
        BigInteger C;
        C[0]=max(A[0], B[0]);
        for (int i=1; i<=C[0]; i++)
            C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
        if (C[C[0]+1] > 0) C[0]++;
        return C;
    }
    bool operator == (const BigInteger& B){
        for(int i = 0;i < 25;i++)
            if(A[i] != B[i]) return false;
        return true;
    }
    BigInteger operator * (const BigInteger& B){
        BigInteger C;
        C[0]=A[0]+B[0];
        for (int i=1; i<=A[0]; i++)
            for (int j=1; j<=B[0]; j++){
                C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
            }
        if (C[C[0]] == 0) C[0]--;
        return C;
    }
};
/**********大数模板-end************/

struct Trie{
    Trie *next[kind];
    Trie *fail;
    int flag;
    int id;
};
Trie *root,point[maxn];
queue<Trie*> Q;
map<char,int> mp;
int head,tail,idx;
char cha[1005];
int ID(char ch){
    return mp[ch];
}
Trie* NewNode(){
    Trie *temp = &point[idx];
    memset(temp ->next,NULL,sizeof(temp ->next));
    temp ->flag = 0;
    temp ->id = idx++;
    temp ->fail = NULL;
    return temp;
}

void Insert(char *s){
    Trie *p = root;
    for(int i = 0;s[i];i++){
        int x = ID(s[i]);
        if(p ->next[x] == NULL){
            p ->next[x] = NewNode();
        }
        p = p ->next[x];
    }
    p ->flag = 1;
}
void buildFail(){
    while(!Q.empty()) Q.pop();
    Q.push(root);
    Trie *p,*temp;
    while(!Q.empty()){
        temp = Q.front();
        Q.pop();
        for(int i = 0;i < kind;i++){
            if(temp ->next[i]){
                if(temp == root){
                    temp ->next[i] ->fail = root;
                }
                else{
                    p = temp ->fail;
                    while(p){
                        if(p ->next[i]){
                            temp ->next[i] ->fail = p ->next[i];
                            break;
                        }
                        p = p ->fail;
                    }
                    if(p == NULL) temp ->next[i] ->fail = root;
                }
                if(temp ->next[i] ->fail ->flag)
                    temp ->next[i] ->flag = 1;
                Q.push(temp ->next[i]);
            }
            else if(temp == root)
                temp ->next[i] = root;
            else
                temp ->next[i] = temp ->fail ->next[i];
        }
    }
}
BigInteger dp[55][150];    //主串第i位,AC自动机第j个
void solve(int n,int len){
    BigInteger zero;
    zero.set(0);
    for(int i = 0;i < idx;i++)
        dp[0][i].set(0);
    dp[0][0].set(1);
    for(int i = 1;i <= len;i++){
        for(int j = 0;j < idx;j++){
            if(point[j].flag) continue;
            if(dp[i - 1][j] == zero) continue;
            for(int k = 0;k < n;k++){
                int r = point[j].next[k] ->id;
                if(point[r].flag) continue;
                dp[i][r] = dp[i][r] + dp[i - 1][j];
            }
        }
    }
    BigInteger ans;
    ans.set(0);
    for(int i = 0;i < idx;i++){
        ans = ans + dp[len][i];
    }
    ans.print();
}

int main(){
    int n,m,p,Case = 1;
    while(scanf("%d%d%d",&n,&m,&p) != EOF){
        idx = 0;
        root = NewNode();
        scanf("%s",cha);
        for(int i = 0;i < n;i++){
            mp[cha[i]] = i;
        }
        for(int i = 0;i < p;i++){
            scanf("%s",cha);
            Insert(cha);
        }
        buildFail();
        solve(n,m);
    }
    return 0;
}

POJ 1625 Censored!(AC自动机->指针版+DP+大数)题解的更多相关文章

  1. POJ 1625 Censored!(AC自动机+DP+高精度)

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 6956   Accepted: 1887 Descrip ...

  2. poj 1625 (AC自动机好模版,大数好模版)

    题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...

  3. POJ 1625 Censored! [AC自动机 高精度]

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9793   Accepted: 2686 Descrip ...

  4. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

  5. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

  6. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  7. Match:Censored!(AC自动机+DP+高精度)(POJ 1625)

     Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...

  8. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

  9. POJ 1625 Censored ( Trie图 && DP && 高精度 )

    题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...

随机推荐

  1. C++中的三种继承public,protected,private

    ( c++默认class是private继承且class内的成员默认都是private struct 默认位public 继承,struct内成员默认是public  ) 三种访问权限 public: ...

  2. MQTT的学习研究(一)MQTT学习网站

    MQTT的官方推荐网站: http://mqtt.org/software 使用IBM 的MQTT协议实现push消息地址: http://tokudu.com/2010/how-to-impleme ...

  3. JS-记住用户名【cookie封装引申】

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. Fluent Nhibernate Mapping for Sql Views

    Views are mapped the same way tables are mapped except that you should put Readonly() in the mapping ...

  5. java如何使用base64生成图片文件

    import org.apache.commons.codec.binary.Base64; public static void decodeFile(String base64Str,File f ...

  6. matplotlib 散点图scatter

    最近开始学习python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1.scatter函数原型 2.其中散点的形状参数marker如下: 3.其中颜色参数c如 ...

  7. SpringMVC中使用@ResponseBody注解将任意POJO对象返回值转换成json进行返回

    @ResponseBody 作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区. ...

  8. Oracle数据类型之nchar

    nchar(size)  nvarchar2(size) n 代表的意思是编码格式为unicode编码,无论中文或者英文都以一个字符来存放数据. 举例: 比如“a” ,占用一个字符 比如“月”,占用一 ...

  9. pta 习题集 5-15 数组循环左移

    本题要求实现一个对数组进行循环左移的简单函数:一个数组aa中存有nn(>0>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移mm(≥0≥0)个位置,即将aa中的数据由(a0a ...

  10. htop 分析 进程对资源的消耗

    [root@d ~]# htop -hhtop 2.2.0 - (C) 2004-2018 Hisham MuhammadReleased under the GNU GPL. -C --no-col ...