去年杭州区域赛的一道题目,比较简单的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;
}