zoukankan      html  css  js  c++  java
  • dfa最小化,终于完成了。

    采取的方法是hopcroft的填表法,详情见如下代码

      1 #include "nfa_to_dfa.h"
      2 int* dfa_diff_matrix;
      3 
      4 int mini_dfa_number;//这个是最小化的 dfa表的索引
      5 typedef struct _min_dfa_node
      6 {
      7     pdfa_edge begin;
      8     int is_end;//记录是否是接受节点
      9 }min_dfa_node,*pmin_dfa_node;
     10 min_dfa_node mini_dfa_table[100];//设定为100,其实也可以malloc一下,因为我们已经知道了有多少个节点了
     11 //为了偷懒,算了
     12 is_diff(int input_a,int input_b)//判断两个点是不是等价的程序,注意我们传参数的时候默认a比b大
     13 {
     14     int destination_a,destination_b;//临时的转换目标地址
     15     pdfa_edge temp_edge;//遍历邻接表 
     16     char label_traverse;//用来遍历符号表
     17     int for_i;
     18     for(for_i=0;for_i<alpha_size;for_i++)
     19     {
     20         label_traverse=mini_alpha_set[for_i];
     21         temp_edge=current_dfa_table[input_a].begin;
     22         while(temp_edge!=NULL&&temp_edge->label!=label_traverse)
     23         {
     24             temp_edge=temp_edge->next;
     25         }
     26         if(temp_edge==NULL)
     27         {
     28             destination_a=0;
     29         }
     30         else
     31         {
     32             destination_a=temp_edge->dest_dfa_index;
     33         }
     34         temp_edge=current_dfa_table[input_b].begin;
     35         while(temp_edge!=NULL&&temp_edge->label!=label_traverse)
     36         {
     37             temp_edge=temp_edge->next;
     38         }
     39         if(temp_edge==NULL)
     40         {
     41             destination_b=0;
     42         }
     43         else
     44         {
     45             destination_b=temp_edge->dest_dfa_index;
     46         }
     47         if(destination_a==destination_b)
     48         {
     49             //下一次吧
     50         }
     51         else
     52         {
     53             if(destination_a*destination_b==0)
     54             {
     55                 return 1;
     56             }
     57             else
     58             {
     59                 if( destination_a>destination_b)
     60                 {
     61                     if(dfa_diff_matrix[dfa_node_number*(input_a)+(input_b)]!=1)//如果当前无法判别
     62                     {
     63                         if(is_diff(destination_a,destination_b))//如果可以判别 
     64                         {
     65                             dfa_diff_matrix[dfa_node_number*(input_a)+(input_b)]=1;
     66                             return 1;
     67                         }
     68                         else
     69                         {
     70                             //继续判别 
     71                         }
     72                     }
     73                     else
     74                     {
     75                         return 1;
     76                     }
     77                 }
     78                 else
     79                 {
     80                     if(dfa_diff_matrix[dfa_node_number*(input_b)+(input_a)]!=1)//如果当前无法判别
     81                     {
     82                         if(is_diff(destination_b,destination_a))//如果可以判别 
     83                         {
     84                             dfa_diff_matrix[dfa_node_number*(input_b)+(input_a)]=1;
     85                             return 1;
     86                         }
     87                         else
     88                         {
     89                             //继续判别 
     90                         }
     91                     }
     92                     else
     93                     {
     94                         return 1;
     95                     }
     96                 }
     97             }
     98         }
     99     }
    100     return 0;
    101 }
    102 void diff_matrix(void)
    103 {
    104     int already_diff_number;//这个是用来判断有多少个点已经经过了等价性测试
    105     int for_i,for_j;
    106     dfa_diff_matrix=malloc(sizeof(int)*dfa_node_number*dfa_node_number);//分配这个节点
    107     for(for_i=0;for_i<dfa_node_number;for_i++)
    108     {
    109         for(for_j=0;for_j<dfa_node_number;for_j++)
    110         {
    111             dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=0;
    112         }
    113     }
    114     for(for_i=1;for_i<dfa_node_number;for_i++)
    115     {
    116         for(for_j=0;for_j<for_i;for_j++)//这里首先根据是否是接受节点来初始化矩阵
    117         {
    118             if(current_dfa_table[for_i+1].is_end!=current_dfa_table[for_j+1].is_end)
    119             {
    120                 dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=1;
    121             }
    122         }
    123     }
    124     do{
    125         already_diff_number=0;
    126         for(for_i=1;for_i<dfa_node_number;for_i++)
    127         {
    128             for(for_j=0;for_j<for_i;for_j++)
    129             {
    130                 if(dfa_diff_matrix[(for_i)*dfa_node_number+for_j]!=1)
    131                 {
    132                     if(is_diff(for_i,for_j)==1)
    133                     {
    134                         dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=1;
    135                     }
    136                 }
    137             }
    138         }
    139     }while(already_diff_number!=0);//如果本趟处理没有找到新的可分节点,就结束 
    140     for(for_i=0;for_i<dfa_node_number;for_i++)
    141     {
    142         for(for_j=0;for_j<dfa_node_number;for_j++)
    143         {
    144             printf("%d ",dfa_diff_matrix[(for_i)*dfa_node_number+for_j]);
    145         }
    146         printf("
    ");
    147     }
    148 }
    149 void minimize_dfa_matrix(void)//在已经构建好了dfa_diff_matrix后,开始群聚,并建图
    150 {
    151     //现在开始群聚 
    152  int* already_in_group;//用来记录哪些点已经在群里面了
    153  int* temp_group;
    154  int* before_min_access;//这里来标注哪些节点已经通过了最简化dfa的转换 
    155  int group_number=0;//注意群号由0开始 
    156  int* index_of_group;
    157  pdfa_edge temp_edge;//这个是用来重新建立最小化dfa的临时边
    158  pdfa_edge temp_add_edge;//这个是用来往最小dfa里面增加边的临时边
    159  int dest_group_number;//这个是在增加边的时候的目标编号
    160  int **group_set;
    161  int for_i,for_j;
    162  group_set=malloc(sizeof(int)*dfa_node_number);
    163  already_in_group=malloc(sizeof(int)*dfa_node_number);
    164  for(for_i=0;for_i<dfa_node_number;for_i++)
    165  {
    166      already_in_group[for_i]=0;
    167      *(group_set+for_i)=NULL;
    168  }
    169  for(for_i=0;for_i<dfa_node_number-1;for_i++)//聚集 
    170  {
    171      if(already_in_group[for_i]==0)
    172      {
    173          already_in_group[for_i]=1;
    174          temp_group=malloc(sizeof(int)*dfa_node_number);
    175          *(group_set+group_number++)=temp_group;
    176          for(for_j=0;for_j<dfa_node_number;for_j++)
    177          {
    178              temp_group[for_j]=0;
    179          }//注意这里也需要考虑加减1的问题
    180          temp_group[for_i]=1;
    181          for(for_j=for_i+1;for_j<dfa_node_number;for_j++)
    182          {
    183              if(!dfa_diff_matrix[(for_j)*dfa_node_number+for_i])
    184              {
    185                  temp_group[for_j]=1;
    186                  already_in_group[for_j]=1;
    187              }
    188          }
    189      }
    190  }//现在已经完全都聚集为一团了
    191  mini_dfa_number=group_number;
    192  //现在再将节点和群的关系反转
    193  index_of_group=malloc(sizeof(int)*dfa_node_number);
    194  //这里又需要注意加减1的关系,由于这里dfa节点是从1标号的,而我们在index_of_group是从0标号的,要注意
    195  for(for_i=0;for_i<dfa_node_number;for_i++)
    196  {
    197      index_of_group[for_i]=0;
    198  }
    199  for_i=0;
    200  while(*(group_set+for_i)!=NULL)//前面开了一个索引数组,现在来赋值,这样就可以直接得到某个节点所在的群号
    201  {
    202      for(for_j=0;for_j<dfa_node_number;for_j++)
    203      {
    204          if(*(*(group_set+for_i)+for_j)==1)
    205          {
    206              index_of_group[for_j]=for_i;
    207          }
    208      }
    209      for_i++;
    210  }//现在关系已经翻转了
    211  //下一步就是利用这个点与群的关系来新建立一个dfa图
    212  //这里的群号就是节点的编号,由于每个群里面的节点都是等价的,所以只需要找一个节点就行了
    213  for(for_i=1;for_i<=group_number;for_i++)//这里的for_i是用来表示最小dfa图的标号,所以从1开始
    214  {
    215      //对每一个群进行遍历
    216      mini_dfa_table[for_i].begin=NULL;
    217      mini_dfa_table[for_i].is_end=0;
    218      for_j=0;
    219      while(*(*(group_set+for_i-1)+for_j)!=1)//由于group是从0开始标号的,所以要减去1
    220      {
    221          for_j++;
    222      }//找到这个群里面一个节点,注意加减一问题,少犯错误啊,1号节点存储在0号位置上
    223      if(current_dfa_table[for_j+1].is_end)
    224      {
    225          mini_dfa_table[for_i].is_end=1;//标记为结束节点
    226      }
    227      temp_edge=current_dfa_table[for_j+1].begin;
    228      while(temp_edge!=NULL)//重新建设邻接表
    229      {
    230          temp_add_edge=malloc(sizeof(struct _dfa_edge));
    231          temp_add_edge->label=temp_edge->label;
    232          temp_add_edge->next=mini_dfa_table[for_i].begin;
    233          dest_group_number=index_of_group[temp_edge->dest_dfa_index-1]+1;//特别要注意这里的加一和减一
    234          //由于temp_edge->dest_dfa_node是从1开始标号的,而index_of_group是从0开始标号的,所以我们要减一
    235          //同样,又由于最后的最简化dfa的图是从1开始标号的,所以我们要加1;
    236          temp_add_edge->dest_dfa_index=dest_group_number;
    237          mini_dfa_table[for_i].begin=temp_add_edge;
    238          temp_edge=temp_edge->next;
    239      }
    240      //本群的邻接表构建完成
    241  }//所有群的邻接表构建完成
    242 }
    243 void show_mini_dfa(void)//输出图
    244 {
    245     int for_i;
    246     pdfa_edge temp_dfa_edge;
    247     number_of_end_dfa=0;
    248     for(for_i=1;for_i<=mini_dfa_number;for_i++)
    249     {
    250         if(mini_dfa_table[for_i].is_end==1)
    251         {
    252             printf("this node is an destination node ,index is %d
    ",for_i);
    253         }
    254         temp_dfa_edge=mini_dfa_table[for_i].begin;
    255         while(temp_dfa_edge!=NULL)
    256         {
    257             printf("there is an dfa edge from %d to %d with label %c
    ",for_i,temp_dfa_edge->dest_dfa_index,temp_dfa_edge->label);
    258             temp_dfa_edge=temp_dfa_edge->next;
    259         }
    260     }
    261     printf("the minimized dfa is completed
    ");
    262 }
  • 相关阅读:
    Use MVS Dsbame convensions. windows下ftp.exe客户端上传错误
    Sqlserver 2005:数据库快照
    Oracle:使用ASM自动存储管理, 严重推荐
    Thunderbird 邮件客户端:windows 和 ubuntu 或 liunx 下共用的方法
    Oracle:Oracle 10 RAC 安装群集件的准备工作
    SSH
    STL
    ASP生成静态Html文件技术杂谈
    Nessus:网络和主机漏洞评估程序安装试用
    table 的 id 属性不被 document.getElementById支持
  • 原文地址:https://www.cnblogs.com/huangfeidian/p/3158803.html
Copyright © 2011-2022 走看看