上次说,LCS有O(n^2 / logn)的解法。这个解法是在字符集不大的情况下,先预处理,再用位运算做状态转移。
唐文斌曾经翻译过一篇论文,专门讨论这个问题。

应richardxx的要求,我把那篇论文贴在这里:
基于位运算的最长公共子序列算法

下面是练习题(n = 10000 的LCS)
http://acm.whu.edu.cn/oak/problem/problem.jsp?problem_id=1210

和我的解答

#include <stdio.h> 
#include 
<string.h> 

#define    WLEN      32 
#define    LOGWLEN      5 
#define    SMAX      16384 
#define    BITMAX      512 
#define    ALPHASIZE 128 

typedef unsigned 
int WORD; 
typedef 
char INDEX; 

int nwords; 
WORD bit1[BITMAX]; 
WORD bit2[BITMAX]; 
WORD a_strings[ALPHASIZE][BITMAX]; 
WORD 
*pb1,*pb2,*t1; 

WORD bitmask[LOGWLEN]
={0x55555555,0x33333333,0x0f0f0f0f,0x00ff00ff,0x0000ffff}

void alphastrings(INDEX *s,int len) 
    register INDEX 
*p; 
    register 
int i,j; 

    
for (i=0;i<ALPHASIZE;i++for (j=0;j<nwords;j++) a_strings[i][j]=0
    p
=s; 
    j
=len; 
    
for (i=0;i<j;i++) a_strings[*(p++)][i/WLEN]|=1<<(i%WLEN); 
     
    
return
}
 

void bitops(WORD *last,WORD *cur,INDEX index) 
    register WORD x,y; 
    register 
int j; 
    register WORD 
*a_s; 
    register WORD top_borrow,bottombit; 

    a_s
=&a_strings[index][0]; 
    bottombit
=1
    
for (j=0;j<nwords;j++
        y
=*(last++); 
        x
=y|*(a_s++); 
        top_borrow
=(y>>(WLEN-1))&0x1
        y
=((y<<1)|bottombit); 
        
if (x<y) top_borrow=1
        
*(cur++)=x&((x-y)^x); 
        bottombit
=top_borrow; 
    }
 
     
    
return
}
 

int bitcount(WORD *wp) 
    register WORD w,count; 
    register 
int j,rshift,i; 

    count
=0
    
for (i=0;i<nwords;i++
        w
=*(wp++); 
        rshift
=1
        
for (j=0;j<LOGWLEN;j++
            w
=(w&bitmask[j])+((w&~bitmask[j])>>rshift); 
            rshift
<<=1
        }
 
        count
+=w; 
    }
 
     
    
return count; 
}
 

int bitlcs(INDEX *a,int lena,INDEX *b,int lenb) 
    register 
int i; 
    register INDEX 
*pbstring; 
    register 
int j,k; 

    nwords
=(lena+WLEN-1)/WLEN; 
    alphastrings(a,lena); 
    pb1
=&bit1[0]; 
    
for (i=0;i<nwords;i++*pb1++=0
    pb1
=&bit1[0]; 
    pb2
=&bit2[0]; 
    pbstring
=b; 
    
for (i=1;i<=lenb;i++
        bitops(pb1,pb2,
*(pbstring++)); 
        t1
=pb1; pb1=pb2; pb2=t1; 
    }
 
     
    
return bitcount(pb1); 
}
 

int main() 
    
char sa[SMAX],sb[SMAX]; 
    
while (scanf("%s%s",sa,sb)!=EOF) printf("%d\n",bitlcs(sa,strlen(sa),sb,strlen(sb))); 
    
return 0
}
 
posted on 2007-10-19 16:56 Felicia 阅读(1339) 评论(5)  编辑 收藏 引用 所属分类: 动态规划
Comments
  • # re: [动态规划]O(n^2 / logn)的LCS
    richardxx
    Posted @ 2007-12-30 03:37
    想请问下唐的论文的题目是?
    望告知。。
      回复  更多评论   
  • # re: [动态规划]O(n^2 / logn)的LCS
    Felicia
    Posted @ 2007-12-30 10:49
    我已经修改了文章,把那个论文上传了。  回复  更多评论   
  • # re: [动态规划]O(n^2 / logn)的LCS
    richardxx
    Posted @ 2007-12-31 13:38
    很感谢felicia! :> :P  回复  更多评论   
  • # re: [动态规划]O(n^2 / logn)的LCS
    ecnu_zp
    Posted @ 2008-07-15 10:55
    太牛了.  回复  更多评论   
  • # re: [动态规划]O(n^2 / logn)的LCS
    NH2T
    Posted @ 2009-07-03 16:54
    thank u very much
    i love you  回复  更多评论   

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理