1444: [Jsoi2009]有趣的游戏
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 394
[Submit][Status][Discuss]
Description

Input

注意 是0<=P
Output

Sample Input

Sample Output

HINT
30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.
Source
分析:
就是建出Trie图然后构造转移方程高斯消元一发...
然后我好像之前写的AC自动机的构建有些问题,并没有根节点向根节点转移的边,所以貌似出了一些问题...
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
//by NeighThorn
using namespace std;
const int maxn=10+5,maxm=maxn*maxn+5;
int n,l,m,tot,head,tail,q[maxm],id[maxn],vis[maxn];
double t[maxn],a[maxm][maxm];
char s[maxn];
struct Trie{
int cnt,fail,nxt[26];
}tr[maxm];
inline int insert(char *s){
int p=0;
for(int i=0;i<l;i++){
if(!tr[p].nxt[s[i]-'A'])
tr[p].nxt[s[i]-'A']=++tot;
p=tr[p].nxt[s[i]-'A'];
}
tr[p].cnt++;
return p;
}
inline void buildACM(void){
head=tail=0,q[0]=0;
while(head<=tail){
int top=q[head++];
for(int i=0;i<m;i++){
int p=tr[tr[top].fail].nxt[i];
if(!tr[top].nxt[i]) tr[top].nxt[i]=p;
else{
if(top)
tr[tr[top].nxt[i]].fail=p;
q[++tail]=tr[top].nxt[i];
}
}
}
}
inline void gauss(void){
for(int i=0;i<=tot;i++){
int k=i;
while(!fabs(a[k][i])&&k<tot) k++;
if(k!=i)
for(int j=0;j<=tot+1;j++)
swap(a[k][j],a[i][j]);
for(int l=0;l<=tot;l++)
if(l!=i&&fabs(a[l][i])){
double lala=a[l][i]/a[i][i];
for(int s=0;s<=tot+1;s++)
a[l][s]-=lala*a[i][s];
}
}
}
signed main(void){
scanf("%d%d%d",&n,&l,&m);
for(int i=1,x,y;i<=m;i++){
scanf("%d%d",&x,&y),t[i-1]=1.0*x/(double)y;
if(t[i-1]==0.0)
vis[i-1]=1;
}
for(int i=1,flag;i<=n;i++){
scanf("%s",s);flag=0;
for(int j=0;j<l&&!flag;j++)
flag|=vis[s[j]-'A'];
if(flag)
id[i]=-1;
else
id[i]=insert(s);
}
buildACM();a[0][tot+1]=1.0;
for(int i=0;i<=tot;i++){
a[i][i]+=1.0;
if(!tr[i].cnt)
for(int j=0;j<m;j++)
a[tr[i].nxt[j]][i]+=-1.0*t[j];
}
gauss();
for(int i=1;i<=n;i++){
if(id[i]==-1)
puts("0.00");
else
printf("%.2f
",a[id[i]][tot+1]/a[id[i]][id[i]]);
}
return 0;
}
By NeighThorn