【题目大意】

给出单词总数和固定的文章长度M,求出至少包含其中一个单词的可能文章数量。

【思路】

对于至少包含一个的类型,我们可以考虑补集。也就是等于[总的文章可能性总数-不包含任意一个单词的文章总数]有两个注意点:

1.Trie图+DP。Trie图和AC自动机的区别在于,当孩子i为NULL时,则让孩子指针等于fail指针的孩子i,这样就可以继续匹配下去了。因此寻找fail指针的时候,可以不用循环而用判断语句即可。

2.danger表示当前位置包含了单词,所以DP的时候舍去。如果你指向的fail指针是danger的,也就是你的后缀是danger的,那么当前的也是danger的。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=+;
const int MAXM=+;
const int MOD=;
const int NUMA=;
int n,m,cnt=;
struct ACauto
{
int id;
int danger;
ACauto* next[NUMA];
ACauto* fail;
ACauto()
{
danger=;
id=++cnt;
for (int i=;i<NUMA;i++) next[i]=NULL;
fail=NULL;
}
};
ACauto* node[MAXN*MAXM];
int f[MAXN][MAXM*MAXN]; void insert(ACauto* root,char* str)
{
int len=strlen(str);
ACauto* tmp=root; for (int i=;i<len;i++)
{
int index=str[i]-'A';
if (tmp->next[index]==NULL)
{
tmp->next[index]=new ACauto;
node[cnt]=tmp->next[index];
}
tmp=tmp->next[index];
}
tmp->danger=;
} void build(ACauto* root)
{
queue<ACauto*> que;
que.push(root);
while (!que.empty())
{
ACauto* head=que.front();que.pop();
for (int i=;i<NUMA;i++)
{
if (head->next[i]==NULL)
{
if (head==root) head->next[i]=root;
else head->next[i]=head->fail->next[i];
}
else
{
if (head==root) head->next[i]->fail=root;
else
{
head->next[i]->fail=head->fail->next[i];
if (head->next[i]->fail->danger) head->next[i]->danger=;/*注意!*/
}
que.push(head->next[i]);
}
}
}
} void dp(ACauto* root)
{
memset(f,,sizeof(f));
f[][]=;
for (int i=;i<=m-;i++)
for (int j=;j<=cnt;j++)
{
if (!node[j]->danger && f[i][j])
{
for (int k=;k<NUMA;k++)//枚举下一个字母
if (!node[j]->next[k]->danger)
f[i+][node[j]->next[k]->id]=(f[i][j]+f[i+][node[j]->next[k]->id])%MOD;
}
}
} void findres()
{
int ans1=,ans2=;
for (int i=;i<=cnt;i++)
if (!node[i]->danger) ans1=(ans1+f[m][i])%MOD;
for (int i=;i<=m;i++) ans2=(ans2*NUMA)%MOD;
cout<<(ans2-ans1+MOD)%MOD<<endl;
} int main()
{
char str[MAXN];
ACauto* root=new ACauto;
node[]=root;
scanf("%d%d",&n,&m);
for (int i=;i<n;i++)
{
scanf("%s",str);
insert(root,str);
} build(root);
dp(root);
findres();
return ;
}

【Trie图+DP】BZOJ1030[JSOI2007]-文本生成器的更多相关文章

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

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

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

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

  3. bzoj1030 [JSOI2007]文本生成器

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

  4. BZOJ1030: [JSOI2007]文本生成器(Trie图+dp)

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

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

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

  6. BZOJ1030[JSOI2007]文本生成器——AC自动机+DP

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

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

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

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

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5984  Solved: 2523[Submit][Status][Discuss] Descripti ...

  9. BZOJ1030 [JSOI2007]文本生成器[DP+AC自动机]

    我学到现在才是初三学弟的水平..哭 这里相当于求长度为$m$的,字符集$\{A...Z\}$的且不包含任一模式串的文本串个数.这是一个典型的AC自动机匹配计数问题. 设$f_{i,j}$表示在AC自动 ...

随机推荐

  1. servlet线程不安全

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAE9CAIAAABY1Yv/AAAgAElEQVR4nOy9eVxN2/8/viuaU5kqZW

  2. Python3【模块】concurrent.futures模块,线程池进程池

    Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我们就要 ...

  3. Vim中的键映射【转】

    转自:http://www.cnblogs.com/softwaretesting/archive/2011/09/28/2194515.html http://www.pythonclub.org/ ...

  4. Asp.Net Forms获取UEeditor内容

    UEeditor是比较常用的富文本编辑器. 获取编辑器的内容,需要使用js获取,官方提供的方法是:UE.getEditor('editor').getContent(); 官方提供的.net例子中是使 ...

  5. spark 环境搭建坑

    spark的新人会有什么坑 spark是一个以java为基础的,以Scala实现的,所以在你在安装指定版本的spark,需要检查你用的是对应spark使用什么版本的scala,可以通过spark-sh ...

  6. FineReport——弹出新窗体选值并回调

    主要实现的功能: 在主页面,通过单击按钮,弹出窗体,在窗体中通过下拉框选择值并查询,如果是多值,可以通过复选框选择,点击确定,将选中的行的字段值传递给主页面的下拉复选框,定义其编辑后事件进行查询.将想 ...

  7. Leetcode 之Binary Tree Postorder Traversal(44)

    后序遍历,比先序和中序都要复杂.访问一个结点前,需要先判断其右孩子是否被访问过.如果是,则可以访问该结点:否则,需要先处理右子树. vector<int> postorderTravers ...

  8. hdu 2881(LIS变形)

    Jack's struggle Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  9. Maximum Gap——桶排序

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  10. 树莓派使用opencv

    安装 reference1 reference2 注意 安装顺利,但是使用的时候提示 you need install libgtk2.0-dev xxx ,这时候说明你安装的库的顺序不对,你应该先安 ...