给你若干给字符串,再给你一个m,问长度是m的字符串中包含给定字符串的数量mod 10007是多少

这个拿过来啥思路也没有,后来还是看了题解,才知道,原来,原来。。。。那个带fail的Trie还可以搞别的

网上的大多数都是26^m-补集做的,麻烦啊,网上有一个非洲猴的blog写的挺好的

设f[i][j][k]表示什么呢,表示i:0..1 j:0..m k:0...size

表示i状态,匹配到j,在Trie上是k的数量

f[i | val[next[c]]][j + 1][next[c]] += f[i][j][k];对就是这样

我已经把next[c] == NULL的都变成fail了,

提醒按照lrj的白书学的AC自动机的同学们,那个last数组在匹配的所有时候都要循环枚举

提醒我自己当k等于0是不是这个位置是无,而是一个未匹配的点,因为计算last和dp时用last耗时代码量费啊

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
struct AC{
    int ch[100010][30];
    int val[100010];
    char s[100010];
    int f[100010];
    int last[100010];
    int g[2][200][10010];
    int size;
    int len;
    inline int num(char x){
        return x - 'A';
    }
    inline void init(){
        memset(ch, 0, sizeof(ch));
        memset(val, 0, sizeof(val));
        size = 0;
        return;
    }
    inline void insert(){
        int u = 0;
        for(int i = 0; i < len; i ++){
            int c = num(s[i]);
            if(!ch[u][c]){
                ch[u][c] = ++ size;
            }
            u = ch[u][c];
        }
        val[u] = 1;
        return;
    }
    inline void getfail(){
        queue<int> Q;
        for(int i = 0; i < 26; i ++) {
            if(ch[0][i]) {
                Q.push(ch[0][i]);
            }
        }
        while(!Q.empty()){
            int r = Q.front(); Q.pop();
            for(int i = 0; i < 26; i ++){
                int u = ch[r][i];
                if(!u){
                    ch[r][i] = ch[f[r]][i];
                    continue;
                }
                Q.push(u);
                int v = f[r];
                while(v && !ch[v][i]) v = f[v];
                f[u] = ch[v][i];
            }
        }
        return;
    }
    inline int dp(int m){
        for(int i = 0; i <= size; i ++){
            if(!val[i]){
                int j = f[i];
                while(j){
                    if(val[j] == 1){
                        val[i] = 1;
                        break;
                    }
                    j = f[j];
                }
            }
        }
        g[0][0][0] = 1;
        for(int i = 0; i <= 1; i ++){
            for(int j = 0; j < m; j ++){
                for(int k = 0; k <= size; k ++){
                    for(int c = 0; c < 26; c ++){
                        g[i | val[ch[k][c]]][j + 1][ch[k][c]] += g[i][j][k];
                        g[i | val[ch[k][c]]][j + 1][ch[k][c]] %= 10007;
                    }
                }
            }
        }
        int ret = 0;
        for(int k = 0; k <= size; k ++) {
            ret += g[1][m][k];
            ret %= 10007;
        }
        return ret;
    }
} wt;
int main(){
    int N, M;
    scanf("%d%d", &N, &M);
    wt.init();
    for(int i = 1; i <= N; i ++){
        scanf("%s", wt.s);
        wt.len = strlen(wt.s);
        //if(wt.len > M) continue;
        wt.insert();
    }
    wt.getfail();
    printf("%d\n", wt.dp(M));
    return 0;
}

BZOJ1030——文本生成器的更多相关文章

  1. bzoj1030 文本生成器(AC自动机+dp)

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4777  Solved: 1986[Submit][Stat ...

  2. bzoj1030 文本生成器

    题目链接 题意 给出\(n\)个字符串,要构造一个长度为\(m\)的字符串\(S\),使得给出的\(n\)个字符串中至少有一个是\(S\)的子串.问方案数. 思路 \(AC\)自动机+\(DP\) 考 ...

  3. 【BZOJ1030】文本生成器(AC自动机,动态规划)

    [BZOJ1030]文本生成器(AC自动机,动态规划) 题面 BZOJ 题解 超级简单良心送分题 很明显是所有状态-不合法状态 合法状态就是\(26^m\) 不合法状态做一个\(dp\)就好 #inc ...

  4. 【BZOJ1030】[JSOI2007]文本生成器 AC自动机+动态规划

    [BZOJ1030][JSOI2007]文本生成器 Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文 ...

  5. BZOJ1030 JSOI2007 文本生成器 【AC自动机】【DP】*

    BZOJ1030 JSOI2007 文本生成器 Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现 ...

  6. 【bzoj1030】: [JSOI2007]文本生成器 字符串-AC自动机-DP

    [bzoj1030]: [JSOI2007]文本生成器 首先把匹配任意一个的个数的问题转化为总个数-没有一个匹配的个数 先构造AC自动机,然后枚举每一位的字母以及在自动机上的位置 f[i][j]为第i ...

  7. 【BZOJ-1030】文本生成器 AC自动机 + DP

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3253  Solved: 1330[Submit][Stat ...

  8. bzoj1030 [JSOI2007]文本生成器

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2654  Solved: 1100[Submit][Stat ...

  9. C++之路进阶——bzoj1030(文本生成器)

    F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在 ...

随机推荐

  1. mysql forget root password

    http://www.rackspace.com/knowledge_center/article/mysql-resetting-a-lost-mysql-root-password MySQL - ...

  2. 批处理学习:for语句详解【经典】

    大纲 一 前言 二 for语句的基本用法 三 for /f (delims.tokens.skip.eol.userbackq.变量延迟) 四 for /r (递归遍历) 五 for /d (遍历目录 ...

  3. centos 查看是32位还是64位

    查看linux机器是32位还是64位的方法: file /sbin/init 或者 file /bin/ls/sbin/init: ELF 64-bit LSB executable, x86-64, ...

  4. Nginx+HTTPS(SSL/TLS)

    环境 首先确保机器上安装了openssl和openssl-devel rpm -qa | grep openssl #yum install openssl #yum install openssl- ...

  5. VC----SDK下对窗口非客户区的操作

    窗口分成两大部分:客户区和非客户区.非客户区再次细分:标题栏,如图片中顶部深蓝色:左边框,如图片中红色部分:上边框,如图片中绿色部分:右边框,如图片中右侧天蓝色部分:底边框,如图片中下面棕色部分. 之 ...

  6. Redis学习——链表源码分析

    0. 前言 Redis 中的链表是以通用链表的形式实现的,而对于链表的用途来说,主要的功能就是增删改查,所以对于查找来说,redis其提供了一个match函数指针,用户负责实现其具体的匹配操作,从而实 ...

  7. FPS

    游戏的FPS跟什么有关 http://zhidao.baidu.com/link?url=jZJoN_-MTC9fWCBSBaL5vezBp13MRSv8PdCcQMbwX5tiFGzxNEHe7UB ...

  8. php常用时间戳记录

    <?php echo '<br/>'; //php获取今日开始时间戳和结束时间戳 echo "今天"; echo '<br/>'; $beginTod ...

  9. DataGridview 绑定泛型List<T>

    .DataGridView数据绑定对比(DataTable与泛型List): 当DataGridView的DataSource是DataTable的时候,DataTable的数据改变时,DataGri ...

  10. csrf利用EXP

    <html><body><form action="http://www.xxx.com/user/setting/email_bind.html" ...