bzoj1030 [JSOI2007]文本生成器

2024-01-10 02:49

本文主要是介绍bzoj1030 [JSOI2007]文本生成器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门
Description
  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

题解

看到有字符串的题目首先想到的就是能不能用AC自动机,但是这道题要求出现至少一个字符串的方案数,如果每次都判断是否有一个字符串或者它的一个前缀在生成串中出现过几乎是不可能完成的事情,所以要转化一下思路,变成求不合法的字符串的个数,然后用26的m次方减就好了。这样的题几乎都是dp,所以我们就可以尝试推dp方程了。
如果一个字符串在文本串中出现过,那么如果在AC自动机上看,一定是到达了某个打过结束标记的节点。为了防止这种情况的发生,如果我们用f[i][j]表示在生成的文本串中进行到第i个位置,在AC自动机上匹配到第j个位置,那么只要我们不用带有结束标记的节点更新别的节点就好了。这样dp方程就可以推出来了。
这道题有几个需要注意的地方:一开始要将0号节点的所有儿子都赋为非0的值,否则会出现儿子更新0号节点的情况;还有就是在建立失配指针的时候,如果一个节点的Fail指针指向的节点有结束标记,那么这个点也必须有结束标记,否则就有可能出现某个给定的单词成为某个单词的后缀的情况。

CODE:

#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int M=1e4+7;
struct AC
{int ch[26];int fail;bool isend;
}a[10000];
char s[101];
int f[105][10005];
int n,m,tot,ans;
inline void insert()
{int len=strlen(s),now=0;for(int i=0;i<len;i++){if(!a[now].ch[s[i]-'A']) a[now].ch[s[i]-'A']=++tot;now=a[now].ch[s[i]-'A'];}a[now].isend=1;
}
inline void makefail()
{queue<int>q;for(int i=0;i<26;i++)if(a[0].ch[i]) q.push(a[0].ch[i]);while(!q.empty()){int tmp=q.front();q.pop();for(int i=0;i<26;i++){if(!a[tmp].ch[i]){a[tmp].ch[i]=a[a[tmp].fail].ch[i];continue;}a[a[tmp].ch[i]].fail=a[a[tmp].fail].ch[i];if(a[a[a[tmp].ch[i]].fail].isend) a[a[tmp].ch[i]].isend=1;q.push(a[tmp].ch[i]);}}
}
inline int pow(int a,int b)
{int ans=1;for(;b;b>>=1,a=(1ll*a*a)%M)if(b&1) ans=(1ll*ans*a)%M;return ans;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%s",s),insert();for(int i=0;i<26;i++)if(!a[0].ch[i]) a[0].ch[i]=++tot;makefail();f[0][0]=1;for(int i=1;i<=m;i++)for(int j=0;j<=tot;j++)if(!a[j].isend)for(int k=0;k<26;k++)f[i][a[j].ch[k]]=(f[i][a[j].ch[k]]+f[i-1][j])%M;ans=pow(26,m);for(int i=1;i<=tot;i++)if(!a[i].isend) ans=(ans-f[m][i]+M)%M;printf("%d",ans);return 0;
}

总结

一定要考虑到所有的情况;注意转换角度思考;注意细节。

这篇关于bzoj1030 [JSOI2007]文本生成器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/589312

相关文章

Level3 — PART 3 — 自然语言处理与文本分析

目录 自然语言处理概要 分词与词性标注 N-Gram 分词 分词及词性标注的难点 法则式分词法 全切分 FMM和BMM Bi-direction MM 优缺点 统计式分词法 N-Gram概率模型 HMM概率模型 词性标注(Part-of-Speech Tagging) HMM 文本挖掘概要 信息检索(Information Retrieval) 全文扫描 关键词

纸牌函数生成器

此模板用来生成纸牌类的测试数据,本人手打,不合理或缀余的地方希望大神指出。 T=10000(测试数据组数), t (两摞相等的牌,每摞牌的数量); 每张牌用A,2~9,T,J,Q,K;表示牌面大小; 用S,H,C,D;表示花色。 共52张牌。 #include<stdio.h>#include<time.h>#include<stdlib.h>#include<string.

超越IP-Adapter!阿里提出UniPortrait,可通过文本定制生成高保真的单人或多人图像。

阿里提出UniPortrait,能根据用户提供的文本描述,快速生成既忠实于原图又能灵活调整的个性化人像,用户甚至可以通过简单的句子来描述多个不同的人物,而不需要一一指定每个人的位置。这种设计大大简化了用户的操作,提升了个性化生成的效率和效果。 UniPortrait以统一的方式定制单 ID 和多 ID 图像,提供高保真身份保存、广泛的面部可编辑性、自由格式的文本描述,并且无需预先确定的布局。

【生日视频制作】酒吧一群美女车展模特大屏幕视频改字AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程酒吧一群美女车展模特大屏幕视频改字AE模板修改文字特效广软件告生成神器素材祝福玩法AE模板工程 怎么如何做的【生日视频制作】酒吧一群美女车展模特大屏幕视频改字AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤: 安装AE软件 下载AE模板 把AE模板导入AE软件 修改图片或文字 渲染出视频

使用亚马逊Bedrock的Stable Diffusion XL模型实现文本到图像生成:探索AI的无限创意

引言 什么是Amazon Bedrock? Amazon Bedrock是亚马逊云服务(AWS)推出的一项旗舰服务,旨在推动生成式人工智能(AI)在各行业的广泛应用。它的核心功能是提供由顶尖AI公司(如AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI以及亚马逊自身)开发的多种基础模型(Foundation Models,简称FMs)。

css 处理文本不换行的方法

https://www.cnblogs.com/sensualgirl/p/3712332.html

文本分类场景下微调BERT

How to Fine-Tune BERT for Text Classification 论文《How to Fine-Tune BERT for Text Classification?》是2019年发表的一篇论文。这篇文章做了一些实验来分析了如何在文本分类场景下微调BERT,是后面网上讨论如何微调BERT时经常提到的论文。 结论与思路 先来看一下论文的实验结论: BERT模型上面的

python tkinter 文本类组件

Label组件 Label(win,text='文本',justify='center) win指定Label组件的父容器;text指定标签中的文本;justify指定标签中拥有多行文本时,最后一行文本的对齐方式。 from tkinter import *from PIL import Image,ImageTkroot = Tk()root.title("compound")roo

[Python]生成器和yield关键字

生成器和yield关键字 1.生成器介绍: 概述: ​ 它指的是 generator, 类似于以前学过的: 列表推导式, 集合推导式, 字典推导式… 作用: ​ 降低资源消耗, 快速(批量)生成数据. 实现方式: ​ 1.推导式写法. my_generator = (i for i in range(5)) ​ 2.yield写法. def get_generator():for i