http://blog.csdn.net/viphong/article/details/53098489
我有一点不是很懂,这样算出来转移到AC自动机根节点的概率是一个远大于1的数。
按我的理解,因为转移初始就是从根节点出发的,
所以x(0)存储的是从根节点出发的概率(100%)+其他点转移到根节点的概率……
比较抽象,还是当做套路记住吧……(鶸的做法)
#include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; #define N 110 double B[N][N+1],A[N][N+1],x[N],b[N]; int ma[13],size; void guass_jordan() { int n=size; memcpy(B,A,sizeof(A)); for(int i=1;i<=n;++i) B[i][n+1]=b[i]; for(int i=1;i<=n;++i)//枚举:正在消除第i个未知数,之后第i个方程废掉,矩阵行、列-1 { int pivot=i; for(int j=i+1;j<=n;++j)//枚举j:把正在处理的未知数的系数的绝对值最大的方程换到第i行 if(fabs(B[j][i])>fabs(B[pivot][i])) pivot=j; swap(B[i],B[pivot]); //if(fabs(B[i][i])<EPS) //若所有(最大)的该未知数系数为0,说明少一个未知数,有无穷多解 for(int j=i+1;j<=n+1;++j) B[i][j]/=B[i][i]; for(int j=1;j<=n;++j) if(i!=j)//枚举所有的方程,从第j个方程中消去第i个未知数 for(int k=i+1;k<=n+1;++k)//依次把第j个方程中的第k个未知数减去应减的数值 B[j][k]-=B[j][i]*B[i][k]; } for(int i=1;i<=n;++i) x[i]=B[i][n+1]; } queue<int>q; int n,L; int child[110][6],fail[110]; bool tag[110]; void Insert(int S[],int id) { int now=0; for(int i=1;i<=L;++i) { if(!child[now][S[i]-1]) child[now][S[i]-1]=size++; now=child[now][S[i]-1]; } tag[now]=1; ma[id]=now; } void build() { fail[0]=-1; q.push(0); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=0;i<6;++i) if(child[U][i]) { int V=fail[U]; while(V!=-1) { if(child[V][i]) { fail[child[U][i]]=child[V][i]; break; } V=fail[V]; } if(V==-1) fail[child[U][i]]=0; if(tag[fail[child[U][i]]]) tag[child[U][i]]=1; q.push(child[U][i]); } else if(U) child[U][i]=child[fail[U]][i]; } } void Init() { memset(child,0,sizeof(child)); memset(fail,0,sizeof(fail)); memset(tag,0,sizeof(tag)); memset(A,0,sizeof(A)); memset(B,0,sizeof(B)); memset(x,0,sizeof(x)); memset(b,0,sizeof(b)); size=1; } int T; int main() { // freopen("hdu5955.in","r",stdin); int s[13]; scanf("%d",&T); for(;T;--T) { Init(); scanf("%d%d",&n,&L); for(int i=1;i<=n;++i) { for(int j=1;j<=L;++j) scanf("%d",&s[j]); Insert(s,i); } build(); for(int i=0;i<size;++i) { if(!tag[i]) for(int j=0;j<6;++j) A[child[i][j]+1][i+1]+=1.0/6.0; A[i+1][i+1]-=1.0; } b[1]=-1.0; guass_jordan(); for(int i=1;i<n;++i) printf("%.6lf ",x[ma[i]+1]); printf("%.6lf ",x[ma[n]+1]); } return 0; }