bzoj1030 [JSOI2007]文本生成器 - AC自动机+dp

JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?

Input

  输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N (<= 60),GW文本生成器 v6生成的文本固
定长度M;以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包
含英文大写字母A..Z

Output

  一个整数,表示可能的文章总数。只需要知道结果模10007的值。

Sample Input

2 2
A
B

Sample Output

100

Hint

 

题解:

题目中应该很好想到ac自动机来解决这道题,这里我们可以换一种思维方式,问知道的文章不好得出

结果,可以想有多少不认识的文章,就是说,给定的单词一个都不能出现。就是说如果该单词有就认

识,那么单词都要避开。

f[i][j]表示到了i这一位,总共m个,即长度,然后,到了j这一个点,可以获得的方案数。

那么就需要在建立Trie图的时候处理一下。

看这个垃圾图,x,y,z点,y指向z,z为标记节点,因为z为y的后缀

所以y包涵z,y也是不和法的,所以y也需要标记为不可到达。

然后就是转移了,复杂度可以压过。

 1 #include<cstring>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdio>
 6 #include<queue>
 7 #define mod 10007
 8 using namespace std;
 9 
10 int n,m,ans=1,res,cnt=1,f[107][6007];
11 struct Node
12 {
13     int c[26],suf;
14     bool flag;
15 }trie[6007];
16 char ch[107];
17 
18 void insert()
19 {
20     int now=1,len=strlen(ch);
21     for (int i=0;i<len;i++)
22     {
23         if (!trie[now].c[ch[i]-'A']) trie[now].c[ch[i]-'A']=++cnt;
24         now=trie[now].c[ch[i]-'A'];
25     }
26     trie[now].flag=true;
27 }
28 void make_AC()
29 {
30     for (int i=0;i<26;i++)
31         trie[0].c[i]=1;
32     queue<int>q;while(!q.empty()) q.pop();
33     trie[1].suf=0;
34     q.push(1);
35     while(!q.empty())
36     {
37         int u=q.front();q.pop();
38         for (int i=0;i<26;i++)
39             if (trie[u].c[i])
40             {
41                 trie[trie[u].c[i]].suf=trie[trie[u].suf].c[i];
42                 if (trie[trie[trie[u].c[i]].suf].flag) trie[trie[u].c[i]].flag=true;
43                 q.push(trie[u].c[i]);
44             }
45             else trie[u].c[i]=trie[trie[u].suf].c[i];
46     }
47 }
48 inline void dp(int x)
49 {
50     for (int i=1;i<=cnt;i++)
51     {
52         if (trie[i].flag||f[x-1][i]==0) continue;
53         for (int j=0;j<26;j++)
54             f[x][trie[i].c[j]]=(f[x][trie[i].c[j]]+f[x-1][i])%mod;
55     }
56 }
57 int main()
58 {
59     scanf("%d%d",&n,&m);
60     for (int i=1;i<=n;i++)
61     {
62         scanf("%s",ch);
63         insert();
64     }
65     make_AC();
66     f[0][1]=1;
67     for (int i=1;i<=m;i++) dp(i);
68     for (int i=1;i<=m;i++)
69         ans=(ans*26)%mod;    
70     for (int i=1;i<=cnt;i++)
71         if (trie[i].flag==0) res=(res+f[m][i])%mod;
72     printf("%d\n",(ans-res+mod)%mod);     
73 }

 

转载于:https://www.cnblogs.com/fengzhiyuan/p/7732315.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
题目描述 有一个 $n$ 个点的棋盘,每个点上有一个数字 $a_i$,你需要从 $(1,1)$ 走到 $(n,n)$,每次只能往右或往下走,每个格子只能经过一次,路径上的数字和为 $S$。定义一个点 $(x,y)$ 的权值为 $a_x+a_y$,求所有满足条件的路径中,所有点的权值和的最小值。 输入格式 第一行一个整数 $n$。 接下来 $n$ 行,每行 $n$ 个整数,表示棋盘上每个点的数字。 输出格式 输出一个整数,表示所有满足条件的路径中,所有点的权值和的最小值。 数据范围 $1\leq n\leq 300$ 输入样例 3 1 2 3 4 5 6 7 8 9 输出样例 25 算法1 (树形dp) $O(n^3)$ 我们可以先将所有点的权值求出来,然后将其看作是一个有权值的图,问题就转化为了在这个图中求从 $(1,1)$ 到 $(n,n)$ 的所有路径中,所有点的权值和的最小值。 我们可以使用树形dp来解决这个问题,具体来说,我们可以将这个图看作是一棵树,每个点的父节点是它的前驱或者后继,然后我们从根节点开始,依次向下遍历,对于每个节点,我们可以考虑它的两个儿子,如果它的两个儿子都被遍历过了,那么我们就可以计算出从它的左儿子到它的右儿子的路径中,所有点的权值和的最小值,然后再将这个值加上当前节点的权值,就可以得到从根节点到当前节点的路径中,所有点的权值和的最小值。 时间复杂度 树形dp的时间复杂度是 $O(n^3)$。 C++ 代码 算法2 (动态规划) $O(n^3)$ 我们可以使用动态规划来解决这个问题,具体来说,我们可以定义 $f(i,j,s)$ 表示从 $(1,1)$ 到 $(i,j)$ 的所有路径中,所有点的权值和为 $s$ 的最小值,那么我们就可以得到如下的状态转移方程: $$ f(i,j,s)=\min\{f(i-1,j,s-a_{i,j}),f(i,j-1,s-a_{i,j})\} $$ 其中 $a_{i,j}$ 表示点 $(i,j)$ 的权值。 时间复杂度 动态规划的时间复杂度是 $O(n^3)$。 C++ 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值