【Aho-Corasick Automaton】

来源:互联网 发布:餐饮成本核算软件 编辑:程序博客网 时间:2024/05/17 22:20

ZOJ 3494 BCD Code

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int each[10][4] = {0,0,0,0, 0,0,0,1, 0,0,1,0, 0,0,1,1, 0,1,0,0, 0,1,0,1, 0,1,1,0, 0,1,1,1, 1,0,0,0, 1,0,0,1};const int N = 100, L = 21, T = 2, M = 205;const int ND = N*L;const int MOD = 1000000009;int str[N][L], pa[M], pb[M];int n;int next[ND][T], fail[ND], acc[ND], B[ND], cnt;int step[ND][10], total[M][ND], non[M];void read(int *f){char c; while(c=getchar(), c<'0'||c>'9');f[f[0]=1] = c-'0'; while(c=getchar(), c>='0'&&c<='9') f[++f[0]] = c-'0';}void init(){scanf("%d", &n);for(int i=0; i<n; i++) read(str[i]);read(pa); read(pb);}void construct(){cnt = 0;memset(next, 0, sizeof(int)*ND*T);memset(fail, 0, sizeof(int)*ND);memset(acc, 0, sizeof(int)*ND);for(int i=0, p, j; i<n; i++){for(p=0, j=1; j<=str[i][0]; j++) if(next[p][str[i][j]]) p = next[p][str[i][j]];else next[p][str[i][j]] = ++cnt, p = cnt;acc[p] = 1;}int hd(0), tl(0);for(int i=0; i<T; i++) if(next[0][i]) B[++tl] = next[0][i];while(hd<tl){int x = B[++hd]; acc[x] |= acc[fail[x]];for(int i=0; i<T; i++) if(next[x][i]){fail[next[x][i]] = next[fail[x]][i];B[++tl] = next[x][i];} else next[x][i] = next[fail[x]][i];}}void reverse(int *f){ for(int i=1; i<=f[0]/2; i++) swap(f[i], f[f[0]-i+1]); }void dec(int *f){int last = 1; while(!f[last]) ++last;for(int i=1; i<last; i++) f[i] = 9; f[last]--;if(f[f[0]]==0) --f[0];}void predp(int x){/* step */for(int i=0; i<=cnt; i++){for(int num=0, p, j; num<10; num++) {for(p=i, j=0; j<4 && !acc[p]; j++) p = next[p][each[num][j]];step[i][num] = p;}}/*total*/memset(total, 0, sizeof(int)*M*ND);for(int i=0; i<=cnt; i++) total[0][i] = !acc[i];for(int ci=1; ci<=x; ci++) {for(int i=0; i<=cnt; i++) if(!acc[i]) {for(int num=0; num<10; num++) total[ci][i] = (total[ci][i] + total[ci-1][step[i][num]]) % MOD;}}/*non*/non[0] = 0;for(int i=1; i<=x; i++){non[i] = ((non[i-1] + total[i][0])%MOD - total[i-1][step[0][0]]) % MOD;}}int dp(int *f){int ret(non[f[0]-1]), p=0;for(int i=f[0]; i; i--){for(int num = (i==f[0])? 1 : 0;  num < f[i]; num++ ) ret = (ret + total[i-1][step[p][num]]) % MOD;p = step[p][f[i]];if(acc[p]) break;}if(f[0]==0) ret = (ret + total[0][step[0][0]]) % MOD;else  ret = ((ret + total[0][p])%MOD + total[0][step[0][0]])%MOD;return ret;}void maindo(){reverse(pa), reverse(pb);dec(pa);predp(pb[0]);int ans = ((dp(pb) - dp(pa)) % MOD + MOD ) % MOD;printf("%d\n", ans);}void work(){init();construct();maindo();}int main(){freopen("bcd.in", "r", stdin);freopen("bcd.out", "w", stdout);int Tes;scanf("%d", &Tes);while(Tes-->0) work();return 0;}


0 0