题意:给你n个字符串,问你长度为m的字符串且字符串中不含有那n个子串的字符串的数量

解题思路:这道题一开始就不太懂,还以为是组合数学的题目,后面看了别人的博客,才知道这是属于AC自动机的另一种用法,是关于fail数组的运用,因为题目问的是不允许包含那n个字符串,所以我们可以这么想,假设一个trie树每个结点都有A,T,C,G这四个儿子结点,然后我们把这n个字符串存进trie树里面,字符串的结尾标记一下,然后根据fail数组的构造,如果某个结点fail指向的结点被标记了,那么这个结点也是不允许走的,这样,一个符合条件的trie树就建立出来了,剩下的就是矩阵部分。把题目简化成是从结点0出发到其他结点走n步的的所有允许情况;

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=110;
struct matrix
{
ll mat[N][N];
matrix()
{
memset(mat,0,sizeof(mat));
}
}ans,fna;
int trie[N][4];
int fail[N],tot;
bool flag[N];
char s[15];
char c['Z'+1];
int n,m;
void build_trie(char *str)//构建trie树
{
int root=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int id=c[str[i]];
if(trie[root][id]==0)
{
trie[root][id]=++tot;
//cout<<tot<<endl;
}
root=trie[root][id];
}
flag[root]=1;
}
void build_fail()
{
queue<int>q;
for(int i=0;i<4;i++)
{
if(trie[0][i]!=0)
q.push(trie[0][i]);
}
while(!q.empty())
{
int now=q.front();
q.pop();
if(flag[fail[now]])//如果当前结点的指向是不允许的,那么这个点也是不允许的
flag[now]=true;
for(int i=0;i<4;i++)
{
if(!trie[now][i])
{
trie[now][i]=trie[fail[now]][i];
continue;
}
fail[trie[now][i]]=trie[fail[now]][i];
q.push(trie[now][i]);
}
}
}
matrix mul(matrix x,matrix y)
{
matrix tmp;
for(int i=0;i<=tot;i++)
for(int j=0;j<=tot;j++)
for(int k=0;k<=tot;k++)
{
tmp.mat[i][j]+=x.mat[i][k]*y.mat[k][j];
tmp.mat[i][j]%=100000;
}
return tmp;
}
matrix matrixpow(matrix x,ll k)
{
matrix ret;
for(int i=0;i<=tot;i++)
ret.mat[i][i]=1;
while(k)
{
if(k&1)
ret=mul(ret,ans);
ans=mul(ans,ans);
k>>=1;
}
return ret;
}
matrix build_mat()//构建矩阵
{
matrix temp;
for(int i=0;i<=tot;i++)
{
if(flag[i])
continue;
for(int j=0;j<4;j++)
{
if(flag[trie[i][j]])continue;
++temp.mat[i][trie[i][j]];
}
}
return temp;
}
void init()
{
memset(fail,0,sizeof(fail));
memset(trie,0,sizeof(trie));
tot=0;
memset(flag,0,sizeof(flag));
c['A']=0;
c['T']=1;
c['C']=2;
c['G']=3;
}
int main()
{
init();
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
build_trie(s);
}
build_fail();
ans=build_mat();
fna=matrixpow(ans,n);
ll xx=0;
for(int i=0;i<=tot;i++)
{
xx+=fna.mat[0][i];xx%=100000;
}
printf("%lld\n",xx);
}

  

代码:

poj2778(AC自动机+矩阵快速幂)的更多相关文章

  1. poj2778 ac自动机+矩阵快速幂

    给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://we ...

  2. POJ2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...

  3. POJ2778(SummerTrainingDay10-B AC自动机+矩阵快速幂)

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17160   Accepted: 6616 Des ...

  4. poj2778DNA Sequence (AC自动机+矩阵快速幂)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud DNA Sequence Time Limit: 1000MS   Memory ...

  5. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  6. HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)

    和前几天做的AC自动机类似. 思路简单但是代码200余行.. 假设solve_sub(i)表示长度为i的不含危险单词的总数. 最终答案为用总数(26^1+26^2+...+26^n)减去(solve_ ...

  7. POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

    这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...

  8. 考研路茫茫——单词情结 HDU - 2243 AC自动机 && 矩阵快速幂

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  9. POJ 2778 DNA Sequence(AC自动机 + 矩阵快速幂)题解

    题意:给出m个模式串,要求你构造长度为n(n <= 2000000000)的主串,主串不包含模式串,问这样的主串有几个 思路:因为要不包含模式串,显然又是ac自动机.因为n很大,所以用dp不太好 ...

  10. hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...

随机推荐

  1. HTML中特殊符号

  2. 01-html介绍和head标签

    [转]01-html介绍和head标签 主要内容 web标准 浏览器介绍 开发工具介绍 HTML介绍 HTML颜色介绍 HTML规范 HTML结构详解 一.web标准 web准备介绍: w3c:万维网 ...

  3. CRM之分页

    分页简介 分页功能在网页中是非常常见的一个功能,其作用也就是将数据分割成多个页面来进行显示. 使用场景: 当取到的数据量达到一定的时候,就需要使用分页来进行数据分割. 当我们不使用分页功能的时候,会面 ...

  4. 自定义Progress小控件

    progress各种各样的都有,自定义大多数也是简单的,根据业务需求来自己定义,记录一下,先上效果图 本来想找个第三方改改就上的,不过自己的业务需求有点不搭,一下子没找到合适的,也没这么多时间去找了, ...

  5. Python:运算类内建函数列举

    1. divmod() python3.x版本中,整除运算用 “//”,取余可以用 “%”,在某些问题中要同时得到商和余数就需要两步运算,而使用divmod函数可以同时得到商和余数: 函数有两个参数d ...

  6. 【原】Java学习笔记016 - 面向对象

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // this 关键字 ...

  7. Maven的简单使用

    Maven使用 在官网下载maven: http://maven.apache.org/download.cgi 解压到D盘(位置随便) 配置环境变量 打开dos窗口,检测是否成功,出现如下画面表示配 ...

  8. 完成一个java项目需要的一些基础

    包括  1.eclipse关键字      2.文档注      3. jar包的导出与导入 一.elipse关键字 ctry+t       查看父类 ctry+鼠标光标     查看源代码 二.文 ...

  9. [Unity优化]批处理04:MaterialPropertyBlock

    参考链接: https://blog.csdn.net/liweizhao/article/details/81937590 1.在场景中放一些Cube,赋予一个新材质,使用内置shader(Unli ...

  10. MJT's Blog

    This is MJT's blog. Here is a mirror web of his blog.