kmp.c
上传用户:jsljixie
上传日期:2013-08-15
资源大小:827k
文件大小:8k
源码类别:

并行计算

开发平台:

Visual C++

  1. #include <malloc.h>
  2. #include <sys/stat.h>
  3. #include <sys/types.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <mpi.h>
  7. #define  MAX(m,n)    (m>n?m:n)
  8. typedef struct{
  9.    int pedlen;
  10.    int psuffixlen;
  11.    int pednum;
  12. }pntype;
  13. /*对模式串进行周期分析,并计算相应的new和newval值*/
  14. void Next(char *W,int patlen,int *nextval,pntype *pped)
  15. {
  16. int i,j,plen;
  17.     int *next;
  18.     if((next=(int *)malloc((patlen+1)*sizeof(int)))==NULL){
  19.       printf("no enough memoryn");
  20.         exit(1);
  21.     }
  22.    /*计算next和nextval*/    
  23.     next[0]=nextval[0]=-1;
  24.    j=1;
  25.     while(j<=patlen){
  26.     i=next[j-1];
  27.        while(i!=(-1) && W[i]!=W[j-1]) i=next[i];
  28.        next[j]=i+1;
  29.        if(j!=patlen){
  30.            if( W[j]!=W[i+1])
  31.                nextval[j]=i+1;
  32.             else
  33.      nextval[j]=nextval[i+1]; 
  34.        }
  35.         j++;
  36.    } 
  37.     pped->pedlen=patlen-next[patlen]; 
  38.   pped->pednum=(int)(patlen/pped->pedlen); 
  39.     pped->psuffixlen=patlen%pped->pedlen; 
  40.    free(next);
  41. }
  42. /*改进的KMP算法*/
  43. void kmp(char *T,char*W,int textlen,int patlen,int *nextval,pntype *pped,int prefix_flag,int matched_num,int *match,int *prefixlen)
  44. {
  45. int i,j;
  46.    i=matched_num;              
  47.    j=matched_num;           
  48.     while(i<textlen)
  49.     {
  50.      if((prefix_flag==1)&&((patlen-j)>(textlen-i))) {
  51.            break;
  52. }
  53.         while(j!=(-1) && W[j]!=T[i])  j=nextval[j];
  54.         if(j==(patlen-1)) {    
  55. match[i-(patlen-1)]=1;
  56.          if(pped->pednum+pped->psuffixlen==1)
  57.             j = -1 ; 
  58.     else                                   
  59.            j=patlen-1-pped->pedlen; 
  60.         }
  61.     j++;
  62.        i++; 
  63.     }
  64.     (*prefixlen)=j;
  65. }
  66. /*重构模式串以及next函数*/
  67. void Rebuild_info(int patlen,pntype *pped,int *nextval,char *W) 
  68. int i; 
  69.     if (pped->pednum == 1) 
  70.     memcpy(W+pped->pedlen,W,pped->psuffixlen); 
  71. else {  
  72.         memcpy(W+pped->pedlen,W,pped->pedlen);
  73.         for (i=3; i<=pped->pednum; i++){ 
  74.          memcpy(W+(i-1)*pped->pedlen,W,pped->pedlen);
  75.             memcpy(nextval+(i-1)*pped->pedlen,nextval+pped->pedlen,pped->pedlen*sizeof(int));
  76.        } 
  77.         if(pped->psuffixlen!=0){
  78.         memcpy(W+(i-1)*pped->pedlen,W,pped->psuffixlen);
  79.             memcpy(nextval+(i-1)*pped->pedlen,nextval+pped->pedlen,pped->psuffixlen*sizeof(int));            
  80.         }
  81.   } 
  82.  
  83. /*生成文本串*/
  84. void gen_string(int strlen,int pedlen,char *string,int seed)
  85. {
  86. int suffixlen,num,i,j;
  87.     srand(seed);
  88.     for(i=0;i<pedlen;i++){
  89.      num=rand()%26;
  90.         string[i]='a'+num;
  91.     }
  92.     for(j=1;j<(int)(strlen/pedlen);j++)
  93.      strncpy(string+j*pedlen,string,pedlen);
  94.     if((suffixlen=strlen%pedlen)!=0)
  95.      strncpy(string+j*pedlen,string,suffixlen);
  96. }  
  97. /*从文件读入模式串信息*/ 
  98. void GetFile(char *filename,char *place, int *number) 
  99. FILE *fp;
  100.     struct stat statbuf;  
  101.     if ((fp=fopen(filename,"rb"))==NULL) {
  102. printf ("Error open file %sn",filename); 
  103.         exit(0); 
  104.     fstat(fileno(fp),&statbuf);  
  105.     if(((*place)=(char *)malloc(sizeof(char)*statbuf.st_size)) == NULL){
  106. printf ("Error alloc memoryn");
  107.         exit(1);
  108.   }
  109.      
  110.     if (fread((*place),1,statbuf.st_size,fp)!=statbuf.st_size){
  111. printf ("Error in reading numn"); 
  112.         exit(0); 
  113.     fclose (fp); 
  114.     (*number)=statbuf.st_size; 
  115. /*打印运行参数信息*/
  116. void PrintFile_info(char *filename,char *T,int id)
  117. FILE *fp; 
  118. int i;
  119. if ((fp=fopen(filename,"a"))==NULL){
  120. printf ("Error open file %sn",filename); 
  121.         exit(0); 
  122.   fprintf (fp,"The Text on node %d is %s .n",id,T); 
  123.    
  124. fclose (fp); 
  125. /*打印匹配结果*/
  126. void PrintFile_res(char *filename,int *t,int len,int init,int id)
  127. FILE *fp; 
  128. int i;
  129. if ((fp=fopen(filename,"a"))==NULL){
  130. printf ("Error open file %sn",filename); 
  131.         exit(0); 
  132.   fprintf (fp,"This is the match result on node %d n",id); 
  133.     for (i=0; i<=len-1; i++) 
  134.      if(t[i]==1)
  135.   fprintf (fp,"(%d)  +n",i+init); 
  136.      else
  137.    fprintf (fp,"(%d)  -n",i+init);
  138. fclose (fp); 
  139. void main(int argc,char *argv[]) 
  140. char *T,*W; 
  141. int *nextval,*match; 
  142.    int textlen,patlen,pedlen,nextlen_send; 
  143.     pntype pped; 
  144.   int i,myid,numprocs,prefixlen,ready; 
  145.    MPI_Status  status; 
  146. MPI_Init(&argc,&argv); 
  147.     MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 
  148.     MPI_Comm_rank(MPI_COMM_WORLD,&myid); 
  149.     nextlen_send=0;
  150.     ready=1;
  151.     /*读如文本串长度*/
  152.     textlen=atoi(argv[1]);
  153.     textlen=textlen/numprocs;
  154.    pedlen=atoi(argv[2]);
  155.     if((T=(char *)malloc(textlen*sizeof(char)))==NULL){
  156.       printf("no enough memoryn");
  157.         exit(1);
  158.     }
  159.     gen_string(textlen,pedlen,T,myid);
  160. if(myid==0){
  161. PrintFile_info("match_result",T,myid);
  162. if(numprocs>1)
  163. MPI_Send(&ready,1,MPI_INT,1,0,MPI_COMM_WORLD);
  164. }
  165.     else{
  166.    MPI_Recv(&ready,1,MPI_INT,myid-1,myid-1,MPI_COMM_WORLD,&status);
  167. PrintFile_info("match_result",T,myid);
  168. if(myid!=numprocs-1)
  169. MPI_Send(&ready,1,MPI_INT,myid+1,myid,MPI_COMM_WORLD);
  170. }
  171. printf("n");
  172.    
  173. if((match=(int *)malloc(textlen*sizeof(int)))==NULL){
  174. printf("no enough memoryn");
  175. exit(1);
  176. }
  177.   
  178.    /*处理器0读入模式串,并记录运行参数*/
  179.     if(myid==0){ 
  180.    printf("processor num = %d n",numprocs);
  181.      printf("textlen = %dn",textlen*numprocs); 
  182.         GetFile("pattern.dat",&W,&patlen); 
  183.      printf("patlen= %dn",patlen); 
  184.      if((nextval=(int *)malloc(patlen*sizeof(int)))==NULL){
  185.          printf("no enough memoryn");
  186.             exit(1);
  187.         }
  188. /*对模式串进行分析,对应于算法14.6步骤(1)*/
  189.        Next(W,patlen,nextval,&pped);
  190.         if(numprocs>1){
  191.          if (pped.pednum==1) 
  192.             nextlen_send = patlen;
  193.             else 
  194.          nextlen_send = pped.pedlen*2;
  195.         }
  196.     }
  197. /*向各个处理器播送模式串的信息,对应于算法14.6步骤(2)*/
  198.    if(numprocs>1){
  199.       MPI_Bcast(&patlen, 1, MPI_INT, 0, MPI_COMM_WORLD);  
  200.    if(myid!=0)
  201.      if(((nextval=(int *)malloc(patlen*sizeof(int)))==NULL)
  202. ||((W=(char *)malloc(patlen*sizeof(char)))==NULL)){
  203.             printf("no enough memoryn");
  204.              exit(1);
  205.             }
  206.     MPI_Barrier(MPI_COMM_WORLD);
  207.      MPI_Bcast(&pped,3,MPI_INT,0,MPI_COMM_WORLD);  
  208.      MPI_Bcast(&nextlen_send,1,MPI_INT,0,MPI_COMM_WORLD);
  209.      MPI_Bcast(nextval,nextlen_send,MPI_INT,0,MPI_COMM_WORLD); 
  210.      MPI_Bcast(W,pped.pedlen,MPI_CHAR,0,MPI_COMM_WORLD);
  211.     }
  212.     MPI_Barrier(MPI_COMM_WORLD);
  213.     /*调用修改过的KMP算法进行局部串匹配,对应于算法14.6步骤(3)*/
  214.    if(numprocs==1) {
  215.    kmp(T,W,textlen,patlen,nextval,&pped,1,0,match+patlen-1,&prefixlen);
  216.     }
  217.     else { 
  218.      if(myid!=0)
  219.      /*各个处理器分别根据部分串数据以及周期信息重构模式串*/
  220.          Rebuild_info(patlen,&pped,nextval,W); 
  221.      if(myid!=numprocs-1)
  222.    kmp(T,W,textlen,patlen,nextval,&pped,0,0,match+patlen-1,&prefixlen);
  223. else
  224.    kmp(T,W,textlen,patlen,nextval,&pped,1,0,match+patlen-1,&prefixlen);
  225.     MPI_Barrier(MPI_COMM_WORLD);
  226. /*各个处理器进行段间匹配,对应于算法14.6步骤(4)*/
  227.      if(myid<numprocs-1) 
  228.          MPI_Send(&prefixlen,1,MPI_INT,myid+1,99,MPI_COMM_WORLD); 
  229.      if(myid>0) 
  230.      MPI_Recv(&prefixlen,1,MPI_INT,myid-1,99,MPI_COMM_WORLD,&status); 
  231.      MPI_Barrier(MPI_COMM_WORLD);
  232.      if((myid>0)&&(prefixlen!=0))  
  233.     kmp(T-prefixlen,W,prefixlen+patlen-1,patlen,nextval,&pped,1,prefixlen,match+patlen-1-prefixlen,&prefixlen); 
  234.     MPI_Barrier(MPI_COMM_WORLD);
  235.     }
  236. /*输出匹配结果*/
  237. if(myid==0){
  238. PrintFile_res("match_result",match+patlen-1,textlen-patlen+1,0,myid);
  239. if(numprocs>1)
  240. MPI_Send(&ready,1,MPI_INT,1,0,MPI_COMM_WORLD);
  241. }
  242.     else{
  243.    MPI_Recv(&ready,1,MPI_INT,myid-1,myid-1,MPI_COMM_WORLD,&status);
  244. PrintFile_res("match_result",match,textlen,myid*textlen-patlen+1,myid);
  245. if(myid!=numprocs-1)
  246. MPI_Send(&ready,1,MPI_INT,myid+1,myid,MPI_COMM_WORLD);
  247. }
  248. free(T);
  249.     free(W);
  250.     free(nextval);
  251.     MPI_Finalize(); 
  252.  }