1.hdu3247
用ac自动机预处理出所有文本串到文本串的安全距离(即不通过病毒串)
说下为什么不加bfs部分的注释部分,因为他会导致所求的距离不是安全距离,而之所以能保证bfs的正确是因为如果两文本串连接会通过病毒部分的话,那么next一定会先到病毒部分,(因为病毒部分一定是在两个文本串之间会导致next一定优先指向病毒串)比如当前串遍历完了接下来会有01两种选择,如果走零一定会走到病毒串,那就得老老实实走1.
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #include<queue> using namespace std; const int maxa = 60000; const int cha = 2; int dp[10][1024]; int dis[10][maxa]; int point[10]; int n, m, k; int leng[10]; struct Tire{ int next[maxa][cha], fail[maxa], end[maxa]; int root, L; int newnode(){ for(int i = 0; i < cha; i++){ next[L][i] = -1; } end[L++] = 0; return L-1; } void init(){ L = 0; root = newnode(); } int insert(char buf[], int ii){ int len = strlen(buf); int now = root; for(int i = 0; i < len; i++){ int x = buf[i] -'0'; if(next[now][x] == -1) next[now][x] = newnode(); now = next[now][x]; //printf("%d ", now); }//puts(""); end[now] = ii; return now; } void build(){//printf("build\n"); queue<int>Q; fail[root] = root; for(int i = 0; i < cha; i++){ if(next[root][i] == -1) next[root][i] = root; else{ fail[next[root][i]] = root; Q.push(next[root][i]); } } while(!Q.empty()){ int now = Q.front(); Q.pop(); end[now] |= end[fail[now]]; for(int i = 0; i < cha; i++){ if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else{ fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); // printf("**%d %d\n",next[now][i],next[fail[now]][i]); } } } } void bfs(int ii){//printf("bfs\n"); queue<int> que; int vis[maxa]; memset(vis, 0, sizeof(vis)); que.push(point[ii]); vis[0] = 1; dis[ii][point[ii]] = 0; while(!que.empty()){ int now = que.front(); que.pop();//printf("%d %d\n", dis[ii][now], now); for(int i =0; i < 2; i++){ int Next = next[now][i]; if(vis[Next] == 0 && end[Next] != -1){ dis[ii][Next] = dis[ii][now] +1; vis[Next] = 1; que.push(Next); } /*Next = fail[Next]; while(Next){ if(vis[Next] == 0 && end[Next] != -1){ dis[ii][Next] = dis[ii][now] +1; vis[Next] = 1; que.push(Next); } Next = fail[Next]; }*/ } } } int solve(){ memset(dis, -1, sizeof(dis)); for(int i = 0;i < n; i++){ bfs(i); }//printf("solve%d %d\n", dis[0][point[1]], dis[1][point[0]]);//printf("%d %d\n", point[0], point[1]); for(int i =0 ;i < n; i++){ for(int k = 0; k < (1<<n); k++){ dp[i][k] = 10000000; } } for(int i = 0; i < n; i++){ dp[i][(1<<i)] = leng[i]; } for(int i =1 ;i < n; i++){ for(int k = 0; k < n; k++){ for(int j = 0; j < (1<<n); j++){ if(dp[k][j] < 10000000){ for(int h = 0; h < n; h++){ if(!(j&(1<<h)) && dp[k][j]!=-1){ dp[h][j|(1<<h)] = min(dp[h][j|(1<<h)], dp[k][j] + dis[k][point[h]]); } } } } } } int ans = 10000000; for(int i = 0; i < n; i++){ ans = min(ans, dp[i][(1<<n)-1]); } return ans; } }; char buf[1000005]; Tire ac; int main(){ int m; while(scanf("%d%d", &n, &m), n+m){ ac.init(); for(int i =0 ;i < n; i++){ scanf("%s", buf); leng[i] = strlen(buf); point[i]=ac.insert(buf, 1+i); } for(int i =0; i < m; i++){ scanf("%s", buf); ac.insert(buf, -1); } ac.build(); printf("%d\n", ac.solve()); } } /* abcdefg bcdefg cdef de e ssaabcdefg */
2.poj3341
ac自动机加状压dp加广搜优化
#include<iostream> #include<map> #include<string.h> #include<stdio.h> #include<algorithm> #include<queue> using namespace std; const int maxa = 500; const int cha = 4; int n, m, k; int num_[4]; map<char, int> mp; /*struct point{ short a[4]; bool operator <(const point& b)const{ if(a[0] != b.a[0]) return a[0] < b.a[0]; else if(a[1] != b.a[1]) return a[1] < b.a[1]; else if(a[2] != b.a[2]) return a[2] < b.a[2]; else return a[3] < b.a[3]; } }; map<point, int>dp[maxa]; map<point, bool> bo;*/ int dp[500][11*11*11*11]; int num[maxa]; struct Tire{ int next[maxa][cha], fail[maxa]; long long end[maxa], po[maxa]; int root, L; int newnode(){ for(int i = 0; i < cha; i++){ next[L][i] = -1; } end[L] = 0; num[L++] = 0; return L-1; } void init(){ L = 0; root = newnode(); } void insert(char buf[], int ii){ int len = strlen(buf); int now = root; for(int i = 0; i < len; i++){ int x = mp[buf[i]]; if(next[now][x] == -1) next[now][x] = newnode(); now = next[now][x]; //printf("%d ", now); }//puts(""); long long one = 1; end[now] |= (one<<ii); } void build(){ queue<int>Q; fail[root] = root; for(int i = 0; i < cha; i++){ if(next[root][i] == -1) next[root][i] = root; else{ fail[next[root][i]] = root; Q.push(next[root][i]); } } while(!Q.empty()){//printf("*"); int now = Q.front(); end[now] |= end[fail[now]]; long long p = end[now]; while(p){ num[now] += p%2; p /= 2; } Q.pop(); // end[now] |= end[fail[now]]; for(int i = 0; i < cha; i++){ if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else{ fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); // printf("**%d %d\n",next[now][i],next[fail[ now]][i]); } } } } int solve(){//printf("**%d\n", next[1][3]); memset(dp, -1, sizeof(dp)); dp[0][0] = 0; bool vis[11*11*11*11]; memset(vis, 0, sizeof(vis)); queue<int>que; que.push(0); while(!que.empty()){ int now = que.front(); que.pop(); //printf("%d ", now); int wei = 1; for(int i =0;i < 4; i++){/*if(now==1){printf("&&\n"); printf("%d %d\n", wei, num_[i]); }*/ if(now % (wei*(num_[i]+1)) /wei == num_[i]){ wei *= num_[i] +1; continue; } int Next_state = now+wei; if(!vis[Next_state]){ vis[Next_state] = 1; que.push(Next_state); } for(int k = 0; k < L; k++){ /*if(k == 1 && now == 1){ printf("--%d %d\n", next[k][i],Next_state); }*/ if(dp[k][now] == -1)continue; dp[next[k][i]][Next_state] = max(dp[next[k][i]][Next_state], dp[k][now]+num[next[k][i]]); } wei *= (num_[i]+1); } } int ans = 0; int maxn = 1; for(int i = 0;i < 4; i++){ maxn *= num_[i]+1; } for(int k = 0; k < maxn; k++){ for(int i = 0; i < L; i++){//printf("%d %d %d\n", i, k, dp[i][k]); ans = max(ans, dp[i][k]); } }return ans; } }; char buf[45]; Tire ac; int main(){ //freopen("in.cpp","r", stdin); mp['A'] = 0; mp['T'] = 1; mp['G'] = 2; mp['C'] = 3; int n; int Case = 1; while(scanf("%d", &n), n != 0){ memset(num_, 0, sizeof(num_)); ac.init(); for(int i = 0; i < n; i++){ scanf("%s", buf); ac.insert(buf, i); } scanf("%s", buf); memset(num, 0, sizeof(num)); for(int i = 0; buf[i]; i++){ num_[mp[buf[i]]] ++; } ac.build(); printf("Case %d: %d\n", Case ++, ac.solve()); } } /* abcdefg bcdefg cdef de e ssaabcdefg */
3.poj2778
题意,给出一些串,问m个字符组成的串不包含这些串的有多少种情况。
自动机加矩阵快速幂。
矩阵相乘就是第i行第j列的数就是前一个矩阵的第i行,与后一矩阵的第j列,要保证前一个矩阵的列数等于后一个矩阵的行数。
构造的时候,只要把那些通向结点或通向的点的fild指向结点的节点去掉,其他正常
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #include<queue> #include<map> using namespace std; const int maxa = 105; const int cha = 4; #define LL long long int n, m, k; map<char, int> mp; const int mod = 100000; struct Matrix{ int a[maxa][maxa]; Matrix(){ memset(a, 0, sizeof(a)); } Matrix operator *(const Matrix &b)const { Matrix ret; for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) { int tmp=(long long)a[i][k]*b.a[k][j]%mod; ret.a[i][j]=(ret.a[i][j]+tmp)%mod; } return ret; }/* Matrix operator *(const Matrix &b) const{ Matrix tmp; for(int i =0 ;i < n; i++){; for(int j = 0; j < n; j++){ for(int k = 0;k <n; k++){ LL lo = (LL) (tmp.a[i][j]) + (LL)(a[i][k]) *b.a[k][j]; lo %= mod; tmp.a[i][j] = lo; } } } return tmp; }*/ }; struct Tire{ int next[maxa][cha], fail[maxa], end[maxa]; int root, L; int newnode(){ for(int i = 0; i < cha; i++){ next[L][i] = -1; } end[L++] = 0; return L-1; } void init(){ L = 0; root = newnode(); } void insert(char buf[]){ int len = strlen(buf); int now = root; for(int i = 0; i < len; i++){ int x = mp[buf[i]]; if(next[now][x] == -1) next[now][x] = newnode(); now = next[now][x]; //printf("%d ", now); }//puts(""); end[now] ++; } void build(){ queue<int>Q; fail[root] = root; for(int i = 0; i < cha; i++){ if(next[root][i] == -1) next[root][i] = root; else{ fail[next[root][i]] = root; Q.push(next[root][i]); } } while(!Q.empty()){ int now = Q.front(); if(end[fail[now]]){ end[now] = 1; } Q.pop(); // end[now] |= end[fail[now]]; for(int i = 0; i < cha; i++){ if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else{ fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); // printf("**%d %d\n",next[now][i],next[fail[now]][i]); } } } } Matrix make_Maxtrix(){ Matrix tmp; for(int i = 0; i < L; i++){ for(int k = 0; k < cha; k++){ if(!end[next[i][k]]){ tmp.a[i][next[i][k]] ++; } } } return tmp; } }; Matrix pow(Matrix a,int m) { Matrix ret;// = Matrix(a.n); for(int i = 0; i < n; i++) ret.a[i][i]=1; Matrix tmp=a; while(m) { if(m&1)ret=ret*tmp; tmp=tmp*tmp; m>>=1; } return ret; } char buf[1000005]; Tire ac; int main(){ mp['A'] = 0; mp['T'] = 1; mp['G'] = 2; mp['C'] = 3; int N, M; while(scanf("%d%d", &N, &M)!=EOF){ ac.init(); while(N--){ scanf("%s", buf); ac.insert(buf); } ac.build(); n = ac.L; Matrix a = ac.make_Maxtrix(); Matrix b = pow(a, M);; int ans =0 ; for(int i = 0; i < n ;i++){ ans += b.a[0][i]; ans %= mod; }printf("%d\n", ans); } } /* abcdefg bcdefg cdef de e ssaabcdefg */