点此看题面
大致题意: 给你\(N\)个字符串(只含大写字母),要你求出有多少个由\(M\)个大写字母构成的字符串含有这\(N\)个字符串中的至少一个。

\(AC\)自动机

看到题目,应该比较容易想到用\(AC\)自动机去做。

但是,即使用了\(AC\)自动机,这题直接求还是很麻烦,所以我们需要将题意先转化一下。

题意转化

考虑对于一个由\(M\)个大写字母构成的字符串,无非有两种情况:

  • 第一种情况: 这个字符串中含有这\(N\)个字符串中的至少一个。
  • 第二种情况: 这个字符串中不含这\(N\)个字符串中的任意一个。

题目中让我们求的是第一种情况的方案数,但是,第二种情况的方案数显然更好搞

因此,我们只需求出第二种情况的方案数,再用总方案数\(26^M\)减去它,就是第一种情况的方案数了。

那么第二种情况的方案数怎么求呢?就需要用上\(DP\)了。

动态规划

考虑用\(f_{i,j}\)来表示一共由\(i\)个大写字母构成,最后到达\(Trie\)上第\(j\)个节点的字符串中不含\(N\)个字符串中任意一个字符串的方案数。

初始化时,对于每一个不为这\(N\)个字符串中任意一个字符串的结尾的节点\(i\),\(f_{0,i}=1\)

那么状态转移方程应为\[f_{i,j}=\sum_{k=0}^{25} f_{i-1,node[j].Son[k]}\]

最后,\(f_{m,rt}\)即为第二种情况的方案数。

因此,最后答案就是\(26^M-f_{m,rt}\),至于\(26^M\)要不要用快速幂来优化,那随你便吧(反正我是写了)。
写的过程中还有一些小细节可以优化,这里就不多说了,直接上代码吧。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=ch:(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=ch))
#define M 100
#define SUM 6000
#define MOD 10007
int pp_;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,m,f[M+5][SUM+5];//f[i][j]表示一共由i个大写字母构成,最后到达Trie上第j个节点的字符串中不含n个字符串中任意一个字符串的方案数
namespace AC_Automation//AC自动机
{int rt=1,tot=1;struct Trie{int Son[26],Next,Cnt;}node[SUM+5];queue<int> q;inline void Insert(string st)//将一个字符串st插入Trie中{register int i,nxt,x=rt,len=st.length();for(i=0;i<len;++i){if(!node[x].Son[nxt=st[i]-65]) node[x].Son[nxt]=++tot;x=node[x].Son[nxt];}++node[x].Cnt;//统计这一个节点是否有字符串}inline void GetNext()//求失配指针{register int i,k;q.push(rt);while(!q.empty()){k=q.front(),q.pop();for(i=0;i<26;++i){if(k^rt){if(!node[k].Son[i]) node[k].Son[i]=node[node[k].Next].Son[i];else node[node[k].Son[i]].Next=node[node[k].Next].Son[i],node[node[k].Son[i]].Cnt|=node[node[node[k].Son[i]].Next].Cnt,q.push(node[k].Son[i]);}else {if(!node[k].Son[i]) node[k].Son[i]=rt;else node[node[k].Son[i]].Next=rt,q.push(node[k].Son[i]);}}}}inline int GetAns()//求答案{register int i,j,k;for(GetNext(),i=1;i<=tot;++i) if(!node[i].Cnt) f[0][i]=1;//初始化每个不是n个字符串中某一字符串结尾的节点f[0][i]=1for(i=1;i<=m;++i)//DP的核心代码for(j=1;j<=tot;++j)for(k=0;k<26;++k)//枚举第j个节点的每一个儿子if(!node[j].Cnt) (f[i][j]+=f[i-1][node[j].Son[k]])%=MOD;//若i不是n个字符串中某一字符串结尾的节点,则计算f[i][j]register int res=1,x=26,p=m;//快速幂(写不写无所谓,写了也比O(m)求快不了多少)while(p){if(p&1) (res*=x)%=MOD;(x*=x)%=MOD,p>>=1;}return ((res-f[m][rt])%MOD+MOD)%MOD;//两数相减后可能为负,因此要加上一个MOD}
};
inline void read(int &x)
{x=0;static char ch;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void read_string(string &x)
{x="";static char ch;while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!(~ch)) return;
}
inline void write(int x)
{if(x>9) write(x/10);pc(x%10+'0');
}
int main()
{register int i,j;register string ss;for(read(n),read(m),i=1;i<=n;++i) read_string(ss),AC_Automation::Insert(ss);//将n个字符串插入Trie中return write(AC_Automation::GetAns()),fwrite(pp,1,pp_,stdout),0;//输出答案
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ1030.html

【BZOJ1030】[JSOI2007] 文本生成器(AC自动机上跑DP)相关推荐

  1. [BZOJ1030] [JSOI2007] 文本生成器 (AC自动机 dp)

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

  2. [BZOJ1030]:[JSOI2007]文本生成器(AC自动机+DP)

    题目传送门 题目描述: JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群, 他们现在使用的是GW文本生成器v6版.该软件可以随机 ...

  3. [BZOJ1030] [JSOI2007]文本生成器

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Description JSOI交给队员ZYX一个任务,编制一个称之为&qu ...

  4. poj--1625Censored!+AC自动机上的dp+大数

    题目链接:点击进入 其实看起来是完全可以用矩阵做的,但是因为用到了大数的,导致内存开不下,所以用dp写了.其实dp的过程依旧就是在我们用禁止出现单词构建的trie上走m步的过程.我们定义dp[i][j ...

  5. BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 3953  Solved: 1614 [Submit][St ...

  6. [BZOJ1030][JSOI2007]文本生成器

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5025  Solved: 2080 [Submit][St ...

  7. bzoj1030 [JSOI2007] 文本生成器(ACAM+dp)

    求长度为m的,至少包含一个模式串的文本串个数. 我们考虑用所有的个数26m26^m减去一个模式串也不包含的个数. 后者我们可以建出ACAM,然后在ACAM上跑dp即可. #include <cs ...

  8. BZOJ1030: [JSOI2007]文本生成器

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

  9. 1030: [JSOI2007]文本生成器 ac自动机+dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=1030 求长度为m不包含n个子串的种数, 跑完ac自动机之后没办法跑矩阵快速幂,因为状态数比较大(6 ...

最新文章

  1. ES6新特性之字符串扩展
  2. mysql navicat 函数_Navicat for MySQL 函数高级属性讲解
  3. [react] react中修改prop引发的生命周期有哪几个?
  4. java文字旋转90度_菜鸟求助:在 JAVA APPLET 里如何旋转 90 度显示一个字符?
  5. CVPR 2021 | 超越卷积的自注意力模型,谷歌、UC伯克利提出HaloNet
  6. Django-restframework 之频率源码分析
  7. Tensorflow 2 Auto-Encoder
  8. RHEL5.4 x86_64 GCC 4.1.2 升级到4.7.0版过程(含安装MPFR、GMP、MPC过程)
  9. 道德如果一直在滑坡,终会酿成大祸,历朝历代,莫过于是……
  10. 计算机组成原理第三章ppt,计算机组成原理第三章幻灯片(白中英版).ppt
  11. IDM下载资源提示无法连接到服务器,代理,防火墙
  12. 利用计算机可视化画一个矩形,可视化程序设计大作业题目
  13. python怎么算列表的平方_Python中排序形式的元素的平方列表
  14. Spring Boot2.0 - 玩转logback日志
  15. 研究生科研素养提升的测试题
  16. k8s多节点master部署
  17. 代价函数,损失函数,目标函数区别
  18. 低保真原型vs高保真原型,哪一种更适合你的设计?
  19. UDP数据包接收逻辑的优化修改以及对性能的影响
  20. 孙文龙理事长出席第二十届东北亚开源软件推进论坛并发表主题演讲

热门文章

  1. Python线程安全问题及解决方法
  2. Flash中与xml交互时不显示中文的解决办法
  3. C# httpcookie asp.net中cookie的使用
  4. 快排的c++实现(两种实现方式)
  5. TensorFlow入门--实现多层感知机
  6. 摄影测量--测边交会
  7. python装饰器简单理解_python装饰器的简单理解
  8. mysql utf 8bm4 没用_不要在 MySQL 中使用“utf8”,請使用“utf8mb4”
  9. 定积分算法java_变步长梯形积分算法求解函数定积分
  10. android webview capturepicture,android webView截图的4种方法