bzoj1030

AC自动机和DP。

f[i][j] 表示在匹配到第i位置,处于ac自动机的j节点。决策第(i+1)个字母,计算出转移到第j2节点。

f[i+1][j2] += f[i][j];

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxl = 100 + 10;
const int maxn = 6000;
const int MOD = 10007;

char s[maxl];
int a[maxn][26],q[maxn],next[maxn];
int f[maxl][maxn];
bool flag[maxn];
int n,m,cnt=1;

void insert(char s[]) {
    int cur = 1,len = strlen(s);
    for(int i = 0,c; i < len;i++) {
        c = s[i] - ‘A‘;
        if(a[cur][c]) cur = a[cur][c];
        else cur = a[cur][c] = ++cnt;
    }
    flag[cur] = 1;
}

void AC_automaton() {
    int l=0,r=0,cur;
    q[r++] = 1,next[1] = 0;
    while(l < r) {
        cur = q[l++];
        for(int i=0,k;i<26;i++)
            if(a[cur][i]) {
                k = next[cur];
                while(!a[k][i]) k = next[k];
                next[a[cur][i]] = a[k][i];
                if(flag[a[k][i]]) flag[a[cur][i]]= 1;
                q[r++] = a[cur][i];
            }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i = 0; i < 26; i++)
        a[0][i] = 1;
    for(int i = 1; i <= n; i++)
        scanf("%s",s),insert(s);
    AC_automaton();
    f[0][1] = 1;
    for(int i = 1; i <= m; i++) {
        for(int j = 1; j <= cnt; j++)
            if(!flag[j] && f[i-1][j])
                for(int k = 0; k < 26; k++) {
                    int cur = j;
                    while(!a[cur][k]) cur = next[cur];
                    f[i][a[cur][k]] = (f[i][a[cur][k]]+f[i-1][j])%MOD;
                }
    }
    int res1=1,res2=0;
    for(int i = 1; i <= m; i++) res1 = (res1*26)%MOD;
    for(int i = 1; i <= cnt; i++) if(!flag[i])
        res2 = (res2+f[m][i])%MOD;
    printf("%d\n",(res1-res2+MOD)%MOD);
    return 0;
}
时间: 2024-11-05 19:29:57

bzoj1030的相关文章

【bzoj1030】 JSOI2007—文本生成器

http://www.lydsy.com/JudgeOnline/problem.php?id=1030 (题目链接) 题意 给出$n$个单词,问有多少个长度为$m$的文本中至少包含一个单词. Solution 构造好AC自动机以后在上面dp,$f[i][j]$表示长度为$i$匹配到自动机上节点$j$时的没有被任意单词匹配的文本个数.转移枚举接在第$j+1$个位置的字符是哪一个,并且保证走过的节点没有一个是结束节点就可以了. 细节 0号节点为root. 代码 // bzoj1030 #inclu

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

[BZOJ1030][JSOI2007]文本生成器 Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中每个字节都是完全随机的.如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串).但是,即使按照这样的标准

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

[bzoj1030]: [JSOI2007]文本生成器 首先把匹配任意一个的个数的问题转化为总个数-没有一个匹配的个数 先构造AC自动机,然后枚举每一位的字母以及在自动机上的位置 f[i][j]为第i位在j的位置且没有匹配过任何一个串的个数 然后26^m-sum(f[m][j])就是答案 还有就是当p->fail一直到root的路径上只要有一个点是一个串的终点那么点f[i][p]就要ban掉 因为这个WA了好多次 1 /* http://www.cnblogs.com/karl07/ */ 2

BZOJ1030:[JSOI2007]文本生成器

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4859  Solved: 2019[Submit][Status][Discuss] Description JSOI交给队员ZGX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些战舰狗,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中每个字

【bzoj1030】[JSOI2007]文本生成器

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3797  Solved: 1553[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中每个

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

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3253  Solved: 1330[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完

bzoj1030【JSOI2007】文本生成器

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2891  Solved: 1193 [Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中

[JSOI2007][BZOJ1030] 文本生成器|AC自动机|动态规划

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2609  Solved: 1074[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完

AC自动机(BZOJ1030)

#include <cstdio> #include <queue> #include <cstring> using namespace std; const int mo=10007; int cnt; int trie[6101][31]; int val[6101]; int f[6101],last[6101]; int n,m; char st[61][101]; int tmp[101]; int dp[101][6101][2]; int newnode