题意:给出n个模板串,随机一个串,求出现模板串个数的期望(相同算一个)。
做法:比赛时误以为是求模板串出现了几次,用dp[i][j]代表在第i个节点还要走l步的期望,然后记忆化搜索。。不停的wa。。
后来问了别人才知道是看错题目了。做法应该是先求概率,再求期望,用dp[i][j][k]表示走了i步,停在j节点,得到串集合为k的概率。
最后答案就是sum(dp[i][j][k]*(k里串的个数))。
AC代码:
<span style="font-size:14px;">//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll long long
#define ull unsigned long long
#define eps 1e-8
#define NMAX 900000
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
#define mp make_pair
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
const int maxnode = 10*12;
struct AhoCorasick
{
int ch[maxnode][26];
int f[maxnode];
int val[maxnode];
int sz;
void clear()
{
memset(ch[0],0,sizeof(ch[0]));
memset(val,0,sizeof(val));
sz = 1;
}
int idx(char c)
{
return c-'a';
}
void insert(char *s, int v)
{
int u = 0, n = strlen(s);
for(int i = 0; i < n; i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] |= (1<<v);
}
void getFail()
{
queue<int>q;
f[0] = 0;
for(int c = 0; c < 26; c++)
{
int u = ch[0][c];
if(u)
{
f[u] = 0; q.push(u);
}
}
while(!q.empty())
{
int r = q.front(); q.pop();
for(int c = 0; c < 26; c++)
{
int u = ch[r][c];
if(!u)
{
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
val[u] |= val[f[u]];
}
}
}
}ac;
double dp[16][maxnode][1<<8];
int ge[1<<8];
int n,l;
char s[20];//1 14 a 0.422525
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o1.txt","w",stdout);
#endif // GLQ
int cas,pp = 0;
for(int i = 0; i < (1<<8); i++)
{
ge[i] = 0;
for(int j = 0; j < 8; j++) if(i&(1<<j)) ge[i]++;
}
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&l);
ac.clear();
for(int i = 0; i < n; i++)
{
scanf("%s",s);
ac.insert(s,i);
}
ac.getFail();
memset(dp,0,sizeof(dp));
dp[0][0][0] = 1;
for(int i = 0; i < l; i++)
for(int j = 0; j < ac.sz; j++)
for(int k = 0; k < (1<<n); k++) if(dp[i][j][k])
for(int x = 0; x < 26; x++)
{
int next = ac.ch[j][x];
dp[i+1][next][k|ac.val[next]] += dp[i][j][k]/26.0;
}
double ans = 0;
for(int i = 0; i < ac.sz; i++)
for(int j = 0; j < (1<<n); j++)
{
ans += dp[l][i][j]*ge[j];
}
printf("%.6lf\n",ans);
}
return 0;
}
</span>