手机腾讯网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为例:
这个矩阵的红色部分就是我们纪录edit(I,j)的编辑距离。我们再通过另外一个矩阵记录一下我们获取以上编辑距离表的每个步骤,0表示未修改, 1表示替换,2表示删除,3表示插入,我们得到以下矩阵。
通过这个矩阵,我们可以知道从batyu修改成beauty,要使代价最小,每一步所进行的操作.通过从矩阵的右下脚处,随着编辑步骤往左上脚遍历,我们就能得到从batyu编辑成beauty每一步进行的操作。如果当前是删除,则往纵坐标减1.如果是替换或者相等,则取对角点,如果是插入,则横坐标减1。以上面矩阵为例,最后一个是arr[6][5]=2说明是删除,纵坐标减1,下一步骤是arr[6][4]为0,说明不变,则横坐标,纵坐标都减1, 下一步为arr[5][3]=0,以此类推,得到如下步骤(绿色框字体)
于是我们得到从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); |
相关推荐
5. 介绍了js增量更新算法的设计,该算法基于将旧文件分成若干块,通过滚动查找算法得到增量更新文件,最终将需要更新的文件块和数据合并成新文件。该算法使用了块大小参数和两个版本间的增量文件数组作为输入,合并...
【威纶通触摸屏MT8051iP V2.0】是通用型的人机界面设备,设计用于工业自动化领域的交互操作。该设备配备了一块4.3英寸的TFT LCD显示屏,分辨率为480 x 272像素,具有400 cd/m²的亮度和500:1的对比度,确保了清晰的...
**MT4 Remote 2.0 知识点详解** MT4 Remote 2.0 是一款专为MetaTrader 4(MT4)交易平台设计的远程访问工具。它允许用户通过手机客户端或其他远程设备实时获取并控制在本地计算机上持续运行的MT4客户端的数据。这款...
MT移动端管理框架 2.2.2 主要更新:使用偏移算法压缩编辑距离算法计算生成的增量文件,减少增量文件的体积大小。为什么使用MT?在快速迭代版本过程中,我们有时候只修改了某个js中的几行代码,却需要用户下载整个js...
### MT算法MT19937:一种高效的伪随机数生成器 #### 一、引言 《Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator》是一篇发表于1998年早期的论文,作者为Makoto ...
7. **效率**:由于MT算法的计算过程主要依赖整数运算和位操作,它在大多数计算机上执行速度非常快。 在`Mersenne-1.1`这个文件中,很可能包含了MT算法的一个特定版本或者实现。具体实现可能包括种子设置函数、...
在IT行业中,智能计算与算法模型的结合正在不断推动各种领域的创新,特别是在金融交易领域。本文将详细探讨“算法模型_智能计算_多算法仓_可是盘_算法模型”这一主题,以及相关压缩包文件中所包含的智能交易模型。 ...
《AE脚本-MG运动图形高级脚本V2版本aescripts Mt.Mograph Motion v2.0(附教程)》 Adobe After Effects(简称AE)是一款强大的视频特效制作软件,广泛应用于影视后期、动画制作等领域。在AE中,脚本的使用能够极大...
标题中的"mt1d_大地电磁_matlab_MT算法_"表明我们关注的是一个使用MATLAB实现的一维大地电磁(MT)正演模型。大地电磁法是一种无损地球探测技术,广泛应用于地质勘探、矿产资源调查等领域,通过测量地表电磁场的变化...
DeMark轴点的计算通常涉及到一系列复杂的数学公式和规则,KeyFinder 2.0脚本内部很可能实现了这些算法的优化版本,以提高计算效率。在实际应用中,交易者可以结合其他技术指标和市场新闻,综合判断这些轴点的可靠性...
综上所述,这份MT6752 design notice V2.0的文件涵盖了MT6752芯片设计的多个重要方面,从基带通信到热管理,再到特定功能模块的设计细节,为移动设备设计师提供了一系列关键的设计指导和技术支持。这份文件对于设计...
MT管理器2.0+2.3.0.apk
本压缩包中包含了三种非实时业务调度算法:轮转算法(Round Robin, RR)、优先级调度算法(Priority Scheduling, PF)以及PF-MT(可能是PF的多线程变体)算法。 1. **轮转算法 (Round Robin, RR)**:轮转算法是最...
除了基本功能外,MT-iBeacon-V2.0 还具备 OAD (Over-the-Air Download) 无线升级功能,允许用户远程更新设备固件。 1. **PC 端升级**: - 使用 PC 端进行 OAD 升级需要特定的软件工具或平台,具体步骤包括连接设备...
在IT领域,智能算法是解决复杂优化问题的重要工具,而MATLAB作为一种强大的数值计算和建模环境,常常被用于实现这些算法。本资料包聚焦于MATLAB中的智能算法实现,涵盖了遗传算法、蚁群算法、进化算法以及粒子群算法...
《基于MT-CNN的人脸识别算法研究》这篇文章深入探讨了在非强制环境下,尤其是面对复杂的姿势、光照和遮挡情况时,如何有效地进行人脸识别和对齐。人脸识别是人工智能领域的一个重要分支,尤其在安全监控、身份验证等...
### MT6139 数据手册 V2.0 知识点概述 #### 一、MT6139 总览 MT6139 是一款高度集成的射频收发器集成电路,专为全球移动通信系统(GSM850/GSM900)、数字蜂窝通信系统(DCS1800)和个人通信服务(PCS1900)等蜂窝...
威纶通触摸屏MT8051iP1系列V2.0是威纶通公司推出的一款4.3英寸TFTLCD触控屏人机界面产品。该系列触摸屏具有宽输入电压范围10.5~28VDC,能够为用户提供不一样的用户体验。在性能上,MT8051iP1系列V2.0进行了二大提升...
MT6816可能是该项目或芯片的特定型号,而STM32F030是意法半导体(STMicroelectronics)生产的基于ARM Cortex-M0内核的微控制器系列,适合于各种嵌入式应用。 描述中的“MT6816 STM32F030实现绝对角度读取”意味着这...