zoukankan      html  css  js  c++  java
  • HDU 3058 Generator [AC自动机+期望DP]

      给出M个短串,这些短串由前N个大写字母组成。然后随机的按字符生成字符串,每次生成1~N个字符的概率是相等的,当生成串包含任意一个指定短串时,就停止生成。问生成串的长度的期望是多少。

      首先建立Trie图,对每个可能作为短串结束的点都打上标记。用E(x)表示从这个点走到停止生成所需长度的期望。显然,对于打标记的点,E(x)=0。对于没打标记的点E(x)=∑(E(next[x][i])*1/N)+1(0<i<N),next[x][i]是它在trie图中接受字母i后走到的点。

      然后根据Trie图建立方程组,用高斯消元求解E(0)即可。

      高斯消元的精度着实很低,现在的代码能过G++,但C++还是WA。。。。估计还是什么地方精度有问题。。

      

      1 #include <string.h>
      2 #include <stdio.h>
      3 #include <math.h>
      4 #include <algorithm>
      5 #define MAXN 105
      6 const double eps=1e-12;
      7 int cas,n,m;
      8 char s[12];
      9 int next[MAXN][8],flag[MAXN],fail[MAXN],pos;
     10 int newnode(){
     11     memset(next[pos],0,sizeof next[pos]);
     12     flag[pos]=fail[pos]=0;
     13     return pos++;
     14 }
     15 void insert(char *s){
     16     int p=0;
     17     for(int i=0;s[i];i++){
     18         int &x=next[p][s[i]-'A'];
     19         p=x?x:x=newnode();
     20     }
     21     flag[p]=1;
     22 }
     23 int q[MAXN],front,rear;
     24 void makenext(){
     25     q[front=rear=0]=0,rear++;
     26     while(front<rear){
     27         int u=q[front++];
     28         for(int i=0;i<n;i++){
     29             int v=next[u][i];
     30             if(v==0)next[u][i]=next[fail[u]][i];
     31             else q[rear++]=v;
     32             if(v&&u){
     33                 fail[v]=next[fail[u]][i];
     34                 flag[v]|=flag[fail[v]];
     35             }
     36         }
     37     }
     38 }
     39 int id[MAXN],w,h;
     40 double mat[MAXN][MAXN],ans[MAXN];
     41 void makemat(){
     42     w=h=0;
     43     memset(id,0,sizeof id);
     44     memset(mat,0,sizeof mat);
     45     for(int i=0;i<pos;i++)
     46         if(flag[i]==0)id[i]=w++;
     47     for(int u=0;u<pos;u++){
     48         if(flag[u]==0){
     49             mat[h][id[u]]=-n;
     50             mat[h][w]=n;
     51             for(int i=0;i<n;i++){
     52                 int v=next[u][i];
     53                 if(flag[v]==1)continue;
     54                 mat[h][id[v]]+=1.0;
     55             }
     56             h++;
     57         }
     58     }
     59     w++;
     60 }
     61 double gauss(){
     62     makemat();
     63     int row=0,col=0;
     64     for(;row<h&&col<w;col++){
     65         int maxr=row;
     66         for(int i=row+1;i<h;i++)
     67             if(fabs(mat[i][col])>fabs(mat[maxr][col]))maxr=i;
     68         if(fabs(mat[maxr][col])<eps)continue;
     69         if(maxr!=row)for(int i=0;i<w;i++)std::swap(mat[maxr][i],mat[row][i]);
     70         for(int k1=row+1;k1<h;k1++){
     71             double div=mat[k1][col]/mat[row][col];
     72             for(int k2=col;k2<w;k2++){
     73                 mat[k1][k2]-=div*mat[row][k2];
     74             }
     75         }
     76         row++;
     77     }
     78     memset(ans,0,sizeof ans);
     79     for(int i=h-1;i>=0;i--){
     80         double tmp=0;
     81         for(int j=i+1;j<w-1;j++){
     82             tmp+=ans[j]*mat[i][j];
     83         }
     84         ans[i]=(mat[i][w-1]-tmp)/mat[i][i];
     85     }
     86     return -ans[0];
     87 }
     88 int main(){
     89     //freopen("test.in","r",stdin);
     90     scanf("%d",&cas);
     91     while(cas--){
     92         scanf("%d%d",&n,&m);
     93         pos=0;newnode();
     94         for(int i=1;i<=m;i++){
     95             scanf("%s",s);
     96             insert(s);
     97         }
     98         makenext();
     99         double res=gauss();
    100         printf("%.2f\n",res);
    101     }
    102 }
  • 相关阅读:
    java Math类
    JAVA Date类与Calendar类【转】
    java Runtime类
    Java System类
    java 多线程
    java 包
    Java 内部类
    java 抽象类 以及模块方法设计模式,接口
    java 单例模式
    java 关于Java中静态代码块以及构造函数的执行先后顺序
  • 原文地址:https://www.cnblogs.com/swm8023/p/2683829.html
Copyright © 2011-2022 走看看