题意:给一些字符串的集合S和整数n,求满足

  • 长度为n
  • 只含charset = {'A'、'T‘、'G'、'C'}包含的字符
  • 不包含S中任一字符串

的字符串的种类数。

思路:首先对S建立ac自动机,考虑向ac自动机中的每种状态后加charset中的字符,如果终态不为“接受状态”,也就是不与S中的任一字符串匹配,则将这次转移记为有效,方法数加1。这样可以建立状态之间的转移矩阵D,表示由一个状态接受1个字符后的方案数,D自乘n次,就得到了任一状态接受n个字符形成的不同字符串种类数,其中从“0”到“i”的方案都要加到答案里面。

另外,这题的模比较有意思,为100000,既不大也不小,或者说是个比较猥琐的数。对于100*100的矩阵,这样取模当然是吃不消的,方法是对每个点算完后一次性取模。时间由800ms→125ms。

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fillarray(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; #ifndef ONLINE_JUDGE
namespace Debug {
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
}
#endif // ONLINE_JUDGE template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const double EPS = 1e-14; /* -------------------------------------------------------------------------------- */ const int maxn = ;
const int mod = ; int N; struct Matrix {
ll a[maxn][maxn]; Matrix() {
for (int i = ; i < N; i ++) {
for (int j = ; j < N; j ++) {
a[i][j] = ;
}
}
} static Matrix unit() {
Matrix ans;
for (int i = ; i < N; i ++) ans.a[i][i] = ;
return ans;
} Matrix &operator * (const Matrix &that) const {
static Matrix ans;
for (int i = ; i < N; i ++) {
for (int j = ; j < N; j ++) {
ans.a[i][j] = ;
for (int k = ; k < N; k ++) {
ans.a[i][j] += a[i][k] * that.a[k][j];
}
ans.a[i][j] %= mod;
}
}
return ans;
} static Matrix power(Matrix a, int n) {
Matrix ans = unit(), buf = a;
while (n) {
if (n & ) ans = ans * buf;
buf = buf * buf;
n >>= ;
}
return ans;
}
}; struct AC_automaton {
const static int SZ = ;
int f[maxn], last[maxn];
bool val[maxn];
int ch[maxn][SZ];
int sz; int idx(char ch) {
if (ch == 'A') return ;
if (ch == 'T') return ;
if (ch == 'G') return ;
if (ch == 'C') return ; } void init() {
sz = ;
memset(ch[], , sizeof(ch[]));
} void insert(char s[]) {
int u = ;
for (int i = ; s[i]; i ++) {
int c = idx(s[i]);
if (!ch[u][c]) {
memset(ch[sz], , sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz ++;
}
u = ch[u][c];
}
val[u] = true;
} void build() {
queue<int> Q;
f[] = ;
for (int c = ; c < SZ; c ++) {
int u = ch[][c];
if (u) {
f[u] = ;
Q.push(u);
last[u] = ;
}
}
while (!Q.empty()) {
int r = Q.front(); Q.pop();
for (int c = ; c < SZ; c ++) {
int u = ch[r][c];
if (!u) {
ch[r][c] = ch[f[r]][c];
continue;
}
Q.push(u);
int v = f[r];
while (v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]]? f[u] : last[f[u]];
}
}
} void solve(int m) {
N = sz;
Matrix ans;
//Debug::print(sz);
for (int i = ; i < sz; i ++) {
for (int j = ; j < ; j ++) {
if (!val[ch[i][j]] && !last[ch[i][j]]) {
ans.a[i][ch[i][j]] ++;
}
}
}
ans = Matrix::power(ans, m);
int rst = ;
for (int i = ; i < sz; i ++) {
rst = (rst + ans.a[][i]) % mod;
}
printf("%d\n", rst);
} }; AC_automaton ac; int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int n, m;
char s[];
while (cin >> n >> m) {
ac.init();
for (int i = ; i < n; i ++) {
scanf("%s", s);
ac.insert(s);
}
ac.build();
ac.solve(m);
}
return ;
}

[poj2778 DNA Sequence]AC自动机,矩阵快速幂的更多相关文章

  1. [poj2778]DNA Sequence(AC自动机+矩阵快速幂)

    题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...

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

    Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's ve ...

  3. poj 2778 DNA Sequence ac自动机+矩阵快速幂

    链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...

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

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

  5. POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...

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

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

  7. POJ 2778 DNA Sequence (ac自动机+矩阵快速幂)

    DNA Sequence Description It's well known that DNA Sequence is a sequence only contains A, C, T and G ...

  8. DNA Sequence POJ - 2778 AC自动机 && 矩阵快速幂

    It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to ...

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

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

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

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

随机推荐

  1. asp.net core webapi 配置跨域处理

    在Startup.cs文件中的ConfigureServices方法中加入如下代码: //配置跨域处理 services.AddCors(options => { options.AddPoli ...

  2. Linux学习笔记(六)压缩和解压缩命令

    压缩和解压缩命令 zip unzip gzip gunzip bzip2 bunzip2 tar zip (.zip格式的压缩文件) 英文原意:package and compress (archiv ...

  3. Jmeter系列(2)- Jmeter工具介绍、Jmeter安装目录介绍、Jmeter面板介绍

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html Jmeter支持哪些测试场景? Jme ...

  4. 最新VMware虚拟机安装Linux系统-CentOS(详细教程)

    一.前言 最近有网友反应初学Linx不会安装,找了许多教程不是太全面,总会遇到一些要不是启动不了,要不是连不上网,各种问题,为了让大家能够顺利的安装,小乐写了一个非常详细的教程,让大家少入坑. 二.背 ...

  5. vue中使用echarts 制作某市各个街道镇的地图

    我要制作的是青州的各街道镇的地图,于是我上网搜,很感谢这篇文章的作者给的提点和帮助https://www.jianshu.com/p/7337c2f56876 现在我把自己的制作过程做个整理,以山东省 ...

  6. search(8)- elastic4s-search-query模式

    上篇提过query模式除对记录的筛选之外还对符合条件的记录进行了评分,即与条件的相似匹配程度.我们把评分放在后面的博文中讨论,这篇我们只介绍query查询. 查询可以分为绝对值查询和全文查询:绝对值查 ...

  7. c++动态数组的使用

    在c++中,有的时候会遇到变长的数组(不管是一维的还是二维的),这个时候就需要用到动态数组了,并且要用new和delete两个操作符,这俩操作符一般成对使用. 先说一维的动态数组吧,直接上代码 #in ...

  8. php 通过 yield 实现协程有什么使用场景

    来源:https://segmentfault.com/q/1010000010018151 参考:https://www.cnblogs.com/lynxcat/p/7954456.html 协程可 ...

  9. mac使用brew安装mysql5.7

    安装mysql5.7 brew install mysql@5.7 设置环境变量(可能安装完自动生成过了,可以cat ~/.zshrc看一下,有了就不用添加了 ) echo 'export PATH= ...

  10. 使用cat命令清空文件

    比如要清空 /www/aaa.txt cat /dev/null > /www/aaa.txt; 即可.