zoukankan      html  css  js  c++  java
  • 【AC自动机】【高斯消元】hdu5955 Guessing the Dice Roll

    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;
    }
  • 相关阅读:
    bzoj 1031: [JSOI2007]字符加密Cipher
    python re模块实现计算器
    python sys模块和序列化模块
    python time时间模块
    python 发红包的小程序
    python ranndom模块及生成验证码
    python os模块练习题
    python os模块常用命令
    快速排序,归并排序
    选择排序和插入排序
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6501154.html
Copyright © 2011-2022 走看看