题意:给你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. 如何保证MongoDB的安全性?

    上周写了个简短的新闻<MongoDB裸奔,2亿国人求职简历泄漏!>: 根据安全站点HackenProof的报告,由于MongoDB数据库没有采取任何安全保护措施,导致共计202,730,4 ...

  2. vue的项目结构记录

    vue的项目结构 不知道大家有没这样的情况,面对刚配置好的脚手架,创建的文件不知道该放哪个文件下,导致后面开发一些文件不好找,不利于维护. 接下来我说说我项目中的一些文件: 首先是components ...

  3. 在IIS上部署你的ASP.NET Core 2.1项目

    1.在控制面板→程序→启用或关闭Windows功能→勾选Internet Information Services以及Web管理工具下的IIS管理控制台 2.IIS 安装AspNetCoreModul ...

  4. Python开发爬虫之静态网页抓取篇:爬取“豆瓣电影 Top 250”电影数据

    所谓静态页面是指纯粹的HTML格式的页面,这样的页面在浏览器中展示的内容都在HTML源码中. 目标:爬取豆瓣电影TOP250的所有电影名称,网址为:https://movie.douban.com/t ...

  5. 命令行以及Python交互模式下python程序的编写

    一.命令行模式 在Windows开始菜单选择“命令提示符”,就进入到命令行模式,它的提示符类似C:\>: 二.Python交互模式 在命令行模式下敲命令python,就看到类似如下的一堆文本输出 ...

  6. iOS----------输入框UITextField禁止输入空格

    方法一:添加代理 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range rep ...

  7. 深入理解Java内存(图解堆栈)

    深入理解Java内存(图解)--转载 深入理解Java内存(图解) 这篇文章是转自http://blog.csdn.net/shimiso/article/details/8595564博文,自己对其 ...

  8. Python 通过脚本获取Android的apk的部分属性,再通过加密算法生成秘钥。

    Python 通过脚本获取Android的apk的部分属性,再通过加密算法生成秘钥. #!/usr/bin/env python # -*- coding: utf- -*- import os im ...

  9. python粗谈面向对象(二)

    浅谈super() super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象:Python的多继承类是通过mro的方式来保证 ...

  10. 关于tomcat 配置时一闪而过的问题

    TOMCAT JAVA_HOME or JRE_HOME environment variable is not defined correctly 按照教程已经安装了JDK并设置好了JAVA_HOM ...