`
luyongfugx
  • 浏览: 1348 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

手腾MT2.0基于编辑距离计算的增量更新算法

 
阅读更多

手机腾讯网mt2.0(http://mt.tencent.com)终于发布了,这个版本的增量更新算法基于编辑距离计算,做到了字符级别的增量更新,比之前的chunk算法更加精确,减少了chunk算法带来的一些冗余字符的下载,下面我们就来看看mt是如何利用这个算法来实现增量更新的.**(广告:我们的github:https://github.com/mtjs/mt ,如果觉得不错请给我们star)**

首先我们来看看什么是Levenshtein Distance (编辑距离),编辑距离即从一个字符串变换到另一个字符串所需要的最少变化操作步骤,是俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。

那如何计算编辑距离呢。通常我们修改一个字符串为另外一个字符串的时候有集中方法,删除,替换,插入,其他的字符就是不变了,按照编辑代价算,删除,替换,插入这几种操纵的代价是1,即修改一个字符,不变则是0,表示没有修改,即操作代价是0. 首先定义这样一个函数——edit(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。

通过动态规划法(dp),我们很容易得到以下公司:

· if i == 0 且 j == 0,edit(i, j) = 0

· if i == 0 且 j > 0,edit(i, j) = j

· if i > 0 且j == 0,edit(i, j) = i

· if i ≥ 1  且 j ≥ 1 edit(i, j) = min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0

· 我们可以用一个矩阵来纪录这一个过程,以以beauty和batyu为例:

wps_clip_image-31133

这个矩阵的红色部分就是我们纪录edit(I,j)的编辑距离。我们再通过另外一个矩阵记录一下我们获取以上编辑距离表的每个步骤,0表示未修改, 1表示替换,2表示删除,3表示插入,我们得到以下矩阵。

wps_clip_image-10140

通过这个矩阵,我们可以知道从batyu修改成beauty,要使代价最小,每一步所进行的操作.通过从矩阵的右下脚处,随着编辑步骤往左上脚遍历,我们就能得到从batyu编辑成beauty每一步进行的操作。如果当前是删除,则往纵坐标减1.如果是替换或者相等,则取对角点,如果是插入,则横坐标减1。以上面矩阵为例,最后一个是arr[6][5]=2说明是删除,纵坐标减1,下一步骤是arr[6][4]为0,说明不变,则横坐标,纵坐标都减1, 下一步为arr[5][3]=0,以此类推,得到如下步骤(绿色框字体)

wps_clip_image-23657

于是我们得到从batyu 到beauty得修改代价最小得步骤是

0-3-0-3-0-0-2

即,第一位不变,第二位插入一个字符,从beauty里取第二个字符’2’,第三位不变,第四位取第四个字符’u’,第四第五位不变,那我们用一个数组这个操作:

[ [ 1, 0 ], 'e', [ 2, 0 ], 'u', [ 3, 0 ], [ 4, 0 ] ],其中数组表示不变,字符表示插入或者替换。

我们进一步压缩有顺序得数组得到: 
[ [ 1, 1 ], 'e', [ 2, 1 ], 'u', [ 3, 2 ] ]

其中得数组表示,从第几个字符开始n个字符不变,这就是传说中得增量文件。

通过这个增量文件数组和源字符串batyu我们很容易得到新字符串:

beauty=”batyu”.substr(1-1,1)+’e’+”batyu”.substr(2-1,1)+’u’+”batyu”.substr(3-1,2);

这就是我们mt2.0得增量更新算法,啥也不说了,我们上代码:

001 function lcsDiff(source,target){
002 var SAME= 0,REPLACE= 1,DELETE= 2,INSERT=3;
003 var sourceArr=source.split('');
004 //var sLength=sourceArr.length;
005 var targetArr=target.split('');
006 //var tLength=targetArr.length;
007 //编辑距离矩阵
008 var disMatrix=[];
009 //步骤矩阵
010 var stepMatrix=[];
011 //生成一个空矩阵,二维数组
012 for(var i=0;i<=sourceArr.length;i++){
013     disMatrix[i]=[];
014     stepMatrix[i]=[];
015     for(var j=0;j<=targetArr.length;j++){
016         disMatrix[i][j]=0;
017         stepMatrix[i][j]=0;
018     }
019 }
020  
021  console.log(disMatrix);
022  console.log(stepMatrix);
023 for(var i=0;i<=sourceArr.length;i++){
024     for(var j=0;j<=targetArr.length;j++){
025         // console.log(i+" "+j);
026         //在第0步,由于都是空,所以是0
027         if(i==0&&j==0){
028             disMatrix[i][j]=0;
029             stepMatrix[i][j]=SAME;
030         }
031         else if(i==0&&j>0){
032             disMatrix[i][j]=j;
033             stepMatrix[i][j]=INSERT;
034         }
035         else if(j==0&&i>0){
036             disMatrix[i][j]=i;
037             stepMatrix[i][j]=DELETE;
038         }
039         else if(i>0&&j>0){
040             var sameStep=(sourceArr[i-1]===targetArr[j-1]),
041                 delStep=disMatrix[i-1][j]+1,
042                 insertStep=disMatrix[i][j-1]+1,
043                 replaceStep=disMatrix[i-1][j-1]+(sameStep?0:1);
044             //console.log(i+' '+j+":"+replaceStep+' '+delStep+' '+insertStep+" v:"+sourceArr[i-1]+' '+targetArr[j-1]);
045             //console.log(i+' '+j+":"+replaceStep+' '+delStep+' '+insertStep);
046             disMatrix[i][j]=Math.min(replaceStep,delStep,insertStep);
047             var stepAct=disMatrix[i][j];
048             switch(stepAct){
049                 case replaceStep:
050                     stepMatrix[i][j]=sameStep?SAME:REPLACE;
051                     break;
052                 case insertStep:
053                     stepMatrix[i][j]=INSERT;
054                     break;
055                 case delStep:
056                     stepMatrix[i][j]=DELETE;
057                     break;
058             }
059             // console.log(i+' '+j+":"+replaceStep+' '+delStep+' '+insertStep+' act :'+stepMatrix[i][j]);
060         }
061     }
062 }
063 console.log("disMatrix:");
064 console.log(disMatrix);
065 console.log("stepMatrix:");
066 console.log(stepMatrix);
067 var diff=[];
068 for(i=sourceArr.length,j=targetArr.length;i>0&&j>0;){
069     var step=stepMatrix[i][j];
070     console.log('=========================='+i+' '+j+':'+step);
071     switch(step){
072         case SAME:
073             diff[j-1]=[i,SAME];
074             i--;j--;
075             break;
076         case REPLACE:
077             diff[j-1]=targetArr[j-1];
078             i--;j--;
079             break;
080         case DELETE:
081             diff[j-1]=DELETE;
082             i--;
083             break;
084         case INSERT:
085             diff[j-1]=targetArr[j-1];
086             j--;
087             break;
088  
089     }
090  
091  
092 }
093  
094 console.log(diff);
095 var preItem,tempStr='',tempArr,reArr=[];
096 for(i=0;i<diff.length;i++){
097     var item=diff[i];
098     if(i==0){
099         if(typeof(item)=='string'){
100             tempStr=item;
101         }
102         else{
103             tempArr=item;
104             tempArr[1]=1;
105         }
106         //continue;
107     }
108     else{
109         if(typeof(item)=='string'){
110             tempStr=tempStr+item;
111             if(typeof(preItem)=='object'){
112                 reArr.push(tempArr);
113             }
114         }
115         else{
116  
117             if(typeof(preItem)=='string'){
118                 tempArr=item;
119                 tempArr[1]=tempArr[1]+1;
120                 reArr.push(tempStr);
121                 tempStr='';
122             }
123             else{
124                 if(preItem[0]==(item[0]-1)){
125                     tempArr[1]=tempArr[1]+1;
126                 }
127                 else{
128                     reArr.push(tempArr);
129                     tempArr=item;
130                     tempArr[1]=tempArr[1]+1;
131                 }
132             }
133         }
134     }
135     preItem=item;
136 }
137 if(typeof(preItem)=='string'){
138     reArr.push(tempStr);
139 }
140 else{
141     reArr.push(tempArr);
142 }
143 return reArr;
144 }
145 function mergeLcs(src,diff){
146 var strBuffer='';
147 for(var i=0;i<diff.length;i++){
148     var item=diff[i];
149     if(typeof(item)=='string'){
150         strBuffer=strBuffer+item;
151     }
152     else{
153         strBuffer=strBuffer+src.substr(item[0]-1,item[1]);
154     }
155 }
156 return strBuffer;
157  
158 }
159  
160  
161 var src="batyu";
162  
163 var target="beauty";
164  
165 console.log(src+" >> "+target);
166  
167 var diffArray=lcsDiff(src,target);
168  
169 console.log(diffArray);
170  
171 var merStr=mergeLcs(src,diffArray);
172  
173 console.log(merStr==target);
174  
175 console.log(merStr);
分享到:
评论

相关推荐

    腾讯MT项目:手腾JS资源版本增量更新方案

    5. 介绍了js增量更新算法的设计,该算法基于将旧文件分成若干块,通过滚动查找算法得到增量更新文件,最终将需要更新的文件块和数据合并成新文件。该算法使用了块大小参数和两个版本间的增量文件数组作为输入,合并...

    威纶通触摸屏MT8051iP V2.0设备手册.pdf

    【威纶通触摸屏MT8051iP V2.0】是通用型的人机界面设备,设计用于工业自动化领域的交互操作。该设备配备了一块4.3英寸的TFT LCD显示屏,分辨率为480 x 272像素,具有400 cd/m²的亮度和500:1的对比度,确保了清晰的...

    MT4 Remote 2.0

    **MT4 Remote 2.0 知识点详解** MT4 Remote 2.0 是一款专为MetaTrader 4(MT4)交易平台设计的远程访问工具。它允许用户通过手机客户端或其他远程设备实时获取并控制在本地计算机上持续运行的MT4客户端的数据。这款...

    MT移动端管理框架 2.2.2.zip

    MT移动端管理框架 2.2.2 主要更新:使用偏移算法压缩编辑距离算法计算生成的增量文件,减少增量文件的体积大小。为什么使用MT?在快速迭代版本过程中,我们有时候只修改了某个js中的几行代码,却需要用户下载整个js...

    MT算法MT19937

    ### MT算法MT19937:一种高效的伪随机数生成器 #### 一、引言 《Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator》是一篇发表于1998年早期的论文,作者为Makoto ...

    MT.rar_MT算法_mt_mtrand.h

    7. **效率**:由于MT算法的计算过程主要依赖整数运算和位操作,它在大多数计算机上执行速度非常快。 在`Mersenne-1.1`这个文件中,很可能包含了MT算法的一个特定版本或者实现。具体实现可能包括种子设置函数、...

    算法模型_智能计算_多算法仓_可是盘_算法模型_

    在IT行业中,智能计算与算法模型的结合正在不断推动各种领域的创新,特别是在金融交易领域。本文将详细探讨“算法模型_智能计算_多算法仓_可是盘_算法模型”这一主题,以及相关压缩包文件中所包含的智能交易模型。 ...

    AE脚本-MG运动图形高级脚本V2版本aescripts Mt.Mograph Motion v2.0(附教程)

    《AE脚本-MG运动图形高级脚本V2版本aescripts Mt.Mograph Motion v2.0(附教程)》 Adobe After Effects(简称AE)是一款强大的视频特效制作软件,广泛应用于影视后期、动画制作等领域。在AE中,脚本的使用能够极大...

    mt1d_大地电磁_matlab_MT算法_

    标题中的"mt1d_大地电磁_matlab_MT算法_"表明我们关注的是一个使用MATLAB实现的一维大地电磁(MT)正演模型。大地电磁法是一种无损地球探测技术,广泛应用于地质勘探、矿产资源调查等领域,通过测量地表电磁场的变化...

    KeyFinder 2.0 - MetaTrader 5脚本.zip

    DeMark轴点的计算通常涉及到一系列复杂的数学公式和规则,KeyFinder 2.0脚本内部很可能实现了这些算法的优化版本,以提高计算效率。在实际应用中,交易者可以结合其他技术指标和市场新闻,综合判断这些轴点的可靠性...

    MT6752 design notice V2.0

    综上所述,这份MT6752 design notice V2.0的文件涵盖了MT6752芯片设计的多个重要方面,从基带通信到热管理,再到特定功能模块的设计细节,为移动设备设计师提供了一系列关键的设计指导和技术支持。这份文件对于设计...

    MT管理器2.0+2.3.0.apk

    MT管理器2.0+2.3.0.apk

    非实时业务调度算法.rar_PF 算法_PF-MT算法_darknessf2p_调度算法_非实时业务调度算法

    本压缩包中包含了三种非实时业务调度算法:轮转算法(Round Robin, RR)、优先级调度算法(Priority Scheduling, PF)以及PF-MT(可能是PF的多线程变体)算法。 1. **轮转算法 (Round Robin, RR)**:轮转算法是最...

    MT-iBeacon-V2.0-用户手册

    除了基本功能外,MT-iBeacon-V2.0 还具备 OAD (Over-the-Air Download) 无线升级功能,允许用户远程更新设备固件。 1. **PC 端升级**: - 使用 PC 端进行 OAD 升级需要特定的软件工具或平台,具体步骤包括连接设备...

    MT 智能算法_matlab_智能算法_

    在IT领域,智能算法是解决复杂优化问题的重要工具,而MATLAB作为一种强大的数值计算和建模环境,常常被用于实现这些算法。本资料包聚焦于MATLAB中的智能算法实现,涵盖了遗传算法、蚁群算法、进化算法以及粒子群算法...

    基于MT-CNN的人脸识别算法研究.pdf

    《基于MT-CNN的人脸识别算法研究》这篇文章深入探讨了在非强制环境下,尤其是面对复杂的姿势、光照和遮挡情况时,如何有效地进行人脸识别和对齐。人脸识别是人工智能领域的一个重要分支,尤其在安全监控、身份验证等...

    MT6139 Data Sheet V2.0

    ### MT6139 数据手册 V2.0 知识点概述 #### 一、MT6139 总览 MT6139 是一款高度集成的射频收发器集成电路,专为全球移动通信系统(GSM850/GSM900)、数字蜂窝通信系统(DCS1800)和个人通信服务(PCS1900)等蜂窝...

    威纶通触摸屏MT8051iP1系列_V2.0_样本说明_功能简介.pdf

    威纶通触摸屏MT8051iP1系列V2.0是威纶通公司推出的一款4.3英寸TFTLCD触控屏人机界面产品。该系列触摸屏具有宽输入电压范围10.5~28VDC,能够为用户提供不一样的用户体验。在性能上,MT8051iP1系列V2.0进行了二大提升...

    MT6816_STM32F030_磁编码器程序编写_MT6816stm32_MT6816_mt6816代

    MT6816可能是该项目或芯片的特定型号,而STM32F030是意法半导体(STMicroelectronics)生产的基于ARM Cortex-M0内核的微控制器系列,适合于各种嵌入式应用。 描述中的“MT6816 STM32F030实现绝对角度读取”意味着这...

Global site tag (gtag.js) - Google Analytics