链接:http://poj.org/problem?id=2778
题意:给定不超过10串,每串长度不超过10的灾难基因;问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中?
DNA:只含'A','T','C','G'四种字符;
思路:这并不是很裸的ac自动机。。没有很明显的文本串匹配过程,但是我们能过通过对灾难基因建好Trie,在跑一下失配边时需要初始化状态转移矩阵了;
状态矩阵:每一次都可以往下一个位置走四个方向,但是要求不能走到单词节点。
(mat[i][j]) ^n: 表示走了n步,i 表示从那个节点开始走,j表示最终的字符(并不是特点的字符,可以表示多个合法的字符);
即:第i个节点到第v个节点之间一步走有几种方法
$ ans = sum limits _{i=0}^{ m size} matleft [0 ight ]left [ i ight ]$
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 #define sqr(a) (a)*(a) typedef pair<int,int> PII; #define A first #define B second #define MK make_pair typedef __int64 ll; template<typename T> void read1(T &m) { T x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } int T,kase = 0,i,j,k,n,m,top; #define mod 100000 struct Matrix{ int d[107][107]; Matrix(int r = 0){ MS0(d); if(r){ for(int i = 0;i < top;i++) d[i][i] = 1; } } Matrix operator*(const Matrix& a)const{ Matrix ans; for(int i = 0;i < top;i++) for(int j = 0;j < top;j++){ for(int k = 0;k < top;k++) ans.d[i][j] = (ans.d[i][j]+1LL*d[i][k]*a.d[k][j]) % mod; } return ans; } }; Matrix Pow(Matrix a,ll m) { Matrix ans(1); while(m){ if(m&1) ans = ans*a; a = a*a; m >>= 1; } return ans; } int h[128]; const int sigma_size = 4; const int maxn = 107; struct Aho_Corasick{ int ch[maxn][sigma_size]; int val[maxn],f[maxn],last[maxn],cnt[maxn]; int sz; map<string,int> ms; Aho_Corasick(){} void init(){sz = 1;val[0] = 0; MS0(ch[0]);MS0(cnt);ms.clear();} int idx(char c){return h[c];} void Insert(char *s,int v){ int u = 0,n = strlen(s); for(int i = 0;i < n;i++){ int c = idx(s[i]); if(!ch[u][c]){ MS0(ch[sz]); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v; } void getFail(){ queue<int> q; f[0] = 0; //初始化队列 for(int c = 0;c < sigma_size;c++){ int u = ch[0][c]; if(u) { f[u] = 0; q.push(u); last[u] = 0;} } while(!q.empty()){ int r = q.front();q.pop(); for(int c = 0;c < sigma_size;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]]; } } } //从文本串中找模板; Matrix Find(){ Matrix ans; for(int i = 0;i < sz;i++){ if(val[i] || last[i]) continue;//合法即可 for(int j = 0;j < 4;j++){ //每个节点都可以生成4个节点 int v = ch[i][j]; if(val[v] || last[v]) continue; ans.d[i][v]++; //也可以表示第i个节点到第v个节点之间一步走有几种方法; } } return ans; } }ac; char p[15]; int main() { ll n,m; //freopen("data.txt","r",stdin); //freopen("out.txt","w",stdout); h['A'] = 0;h['C'] = 1;h['T'] = 2;h['G'] = 3; ac.init(); read2(n,m); rep1(i,1,n){ scanf("%s",p); ac.Insert(p,i); } top = ac.sz; ac.getFail(); Matrix ans = ac.Find(); ans = Pow(ans,m); int cnt = 0; rep0(i,0,top) cnt += ans.d[0][i]; printf("%d ",cnt%mod); return 0; }