标签:
用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 */
4.ZOJ 3494 BCD Code(AC自动机+数位DP)
题目:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串
数位dp加ac自动机
#include<string.h> #include<queue> #include<stdio.h> #include<iostream> using namespace std; const long long maxa = 2005; const long long cha = 2; const long long mod = 1000000009; struct Tire{ long long next[maxa][cha], fail[maxa], end[maxa]; long long root, L; long long newnode(){ for(long long 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[]){ long long len = strlen(buf); long long now = root; for(long long i = 0; i < len; i++){ long long x = buf[i] - ‘0‘; if(next[now][x] == -1){ next[now][x] = newnode(); } now = next[now][x]; }end[now] = 1; } void build(){ queue<int> Q; fail[root] = root; for(long long 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()){ long long now = Q.front();Q.pop(); if(end[fail[now]])end[now] = 1; for(long long 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]); } } } } }ac; /* struct Trie { int next[2010][2],fail[2010]; bool end[2010]; int root,L; int newnode() { for(int i = 0;i < 2;i++) next[L][i] = -1; end[L++] = false; 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++) { if(next[now][buf[i]-‘0‘] == -1) next[now][buf[i]-‘0‘] = newnode(); now = next[now][buf[i]-‘0‘]; } end[now] = true; } void build() { queue<int>Q; fail[root] = root; for(int i = 0;i < 2;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(); if(end[fail[now]])end[now] = true; for(int i = 0;i < 2;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]); } } } }; Trie ac; */ //位数,节点,是否含有,是否有前导零 long long dp[205][maxa][2][2]; long long Next[maxa][10][2]; void NEXT(long long now, long long kk){ long long ok = 0; long long ii = now; for(long long i= 3; i >= 0; i--){ ii = ac.next[ii][((1<<i)&kk)?1:0]; if(ac.end[ii]) ok = 1; } Next[now][kk][0] = ii; Next[now][kk][1] = ok; } long long init(){ memset(dp, -1, sizeof(dp)); for(long long i = 0;i < ac.L; i++){ for(long long k = 0;k < 10; k ++){ NEXT(i, k); } } } long long num[maxa]; long long dfs(long long pos, bool limit, bool yes, long long node, bool isZero){ if(pos == 0){ return yes^1; } if(!limit && isZero == 0 && dp[pos][node][yes][isZero]!=-1) return dp[pos][node][yes][isZero]; long long nn = limit? num[pos]:9; long long res = 0; for(long long i = 0; i <= nn; i++){ if(isZero&& i == 0) res += dfs(pos-1, limit&&i==nn, yes, node, isZero); else res += dfs(pos-1, limit &&(i == nn), Next[node][i][1]|yes, Next[node][i][0], 0); res %= mod; } if(!limit){ dp[pos][node][yes][isZero] = res; } return res; } long long ans(char *a){ long long l = strlen(a); for(long long i = 0; i < l ; i++){ num[l-i] = a[i]-‘0‘; } return dfs(l, 1, 0, 0, 1); } void a_1(char *a){ int l = strlen(a); for(int i = l-1; i>= 0; i--){ if(a[i] == ‘0‘){ a[i] = ‘9‘; }else{ a[i] --;break; } } } char buf[maxa], buf1[maxa]; int main(){ long long t; cin>>t; while(t--){ ac.init(); long long n; cin>>n; while(n--){ scanf("%s", buf); ac.insert(buf); }//printf("*"); ac.build(); init(); scanf("%s%s", buf, buf1); a_1(buf); cout<<(mod+ans(buf1)- ans(buf))%mod<<endl; //printf("%d\n", (mod+ans(buf1)- ans(buf))%mod); } } /* 999992719 4 1 0 1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0 1 10000000000000000000000000000 3 00 0101011 0100000 1 10000000000000000000000000000 5 01010101 010001000010 010100000000100 01010011111111111 0101010100001111111 1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000 805306365 426375876 */
标签:
原文地址:http://www.cnblogs.com/icodefive/p/4451679.html