去年杭州区域赛的一道题目,比较简单的AC自动机
#include <stdio.h> #include <string.h> const int NODE = 1000; const int CH = 26; int tree[NODE][CH], cnt; int fail[NODE], word[NODE], Que[NODE]; int num[128]; char str[20]; double gl[128]; double dp[1010][20]; int mark; int n, m; double sum; int Ins(char *a, int val) { int p = 0; for(; *a; a++) { int c = num[*a]; if(!tree[p][c]) { memset(tree[cnt], 0, CH * sizeof(int)); word[cnt] = 0; tree[p][c] = cnt++; } p = tree[p][c]; } word[p] += val; return p; } void AC() { int *s = Que, *e = Que; for(int i = 0; i < CH; i++) if(tree[0][i]) { fail[tree[0][i]] = 0; *e++ = tree[0][i]; } while(s != e) { int p = *s++; for(int i = 0; i < CH; i++) { if(tree[p][i]) { int v = tree[p][i]; *e++ = v; fail[v] = tree[fail[p]][i]; } else { tree[p][i] = tree[fail[p]][i]; } } } } void solve() { memset(dp, 0, sizeof(dp)); sum = 0; dp[0][0] = 1; for(int i = 0; i < m; i++) { for(int j = 0; j < cnt; j++) if(i >= j) { for(int k = 0; k < CH; k++) { int v = tree[j][k]; dp[i + 1][v] += dp[i][j] * gl[k]; } } if(dp[i+1][mark] >= 0) { sum += dp[i+1][mark]; dp[i+1][mark] = 0; } } /*for(int i = 1; i < m; i++) { for(int j = 0; j < cnt; j++) printf("dp[%d][%d] = %0.4lf ", i, j, dp[i][j]); printf("\n"); }*/ printf("%0.2lf%%\n", sum * 100); } int main() { for(int i = 0; i < 26; i++) num[i + 'a'] = i; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; fail[0] = 0; cnt = 1; memset(tree[0], 0, CH * sizeof(int)); memset(gl, 0, sizeof(gl)); for(int i = 1; i <= n; i++) { double x; scanf("%s%lf", str, &x); gl[str[0] - 'a'] = x; } scanf("%s", str); mark = Ins(str, 1); AC(); solve(); } return 0; }