增量包算法,时间复杂度n+2m

研究了编辑距离、lcd等字符比较的算法,发现它们的时间复杂度和空间复杂度都在n*m,太复杂了。脑海想了下人是怎么比较字符的,联想出动态规划公式,之后就有了这个字符扫描比较法。

设字符s1长度为n,字符s2长度为m,

当s1[n1]!==s2[n2], 扫描s2求出d1,l1,扫描s1求出d2,l2, 比较l1、l2、d1、d2,移动n1、n2,重复这个过程

// 动态公式
// d1==0
// n1=n1+l1 l1>l2 或者 l1==l2 d1<d2
// n2=n2+d1+l1 l1>l2
//
// n1=n1+d2+l2 l1<l2 或者 l1==l2 d1>d2
// n2=n2+l2 l1<l2

//定义两个字符
var s1="afbrcd",s2="aftcdad";

//扫描法,复杂度为 n+m
//生产增量包
function makeChunk(s1,s2) {
  var n=s1.length,m=s2.length;//长度
  var n1=0,n2=0;//扫描点
  const chunkArr=[]
//开始扫描
  while (n1<n&&n2<m){
    let nn1=n1;
    let nn2=n2;
    if(s1[nn1]===s2[nn2]){
      nn1++;
      nn2++;
      while (nn1<n&&nn2<m&&s1[nn1]===s2[nn2]){
        nn1++;
        nn2++;
      }
      chunkArr.push(['e',n1,nn1-n1,n2,nn2])
      n1=nn1;
      n2=nn2;
    }else{
      //求n1,n2,d1,d2,l1,l2
      nn1=n1;
      nn2++;
      while (nn2<m&&s1[n1]!==s2[nn2]){
        nn2++;
      }
      let d1=nn2-n2;
      let l1=0;
      while (nn1<n&&nn2<m&&s1[nn1]===s2[nn2]){
        nn1++;
        nn2++;
        l1++;
      }
      nn2=n2;
      nn1++;
      while (nn1<n&&s1[nn1]!==s2[n2]){
        nn1++;
      }
      let d2=nn1-n1;
      let l2=0;
      while (nn1<n&&nn2<m&&s1[nn1]===s2[nn2]){
        nn1++;
        nn2++;
        l2++;
      }
      //结束
      if(l1>l2){
        chunkArr.push(['a',s2.substr(n2,d1),n1,n2,d1])
        chunkArr.push(['e',n1,l1,n2+d1,l1])
        n1=n1+l1;
        n2=n2+d1+l1;
      }else if(l1<l2){
        // chunkArr.push(['d',n1,d2,s1.substr(n1,d2)])
        chunkArr.push(['e',n1+d2,l2,n2,l2])
        n1=n1+d2+l2;
        n2=n2+l2;
      }else{
        if(d1<d2&&l1>0){
          chunkArr.push(['a',s2.substr(n2,d1),n1,n2,d1])
          n2=n2+d1;
        }else if(d1>d2&&l1>0){
          // chunkArr.push(['d',n1,d2,s1.substr(n1,d2)])
          n1=n1+d2;
        }else{
          var lastC=chunkArr[chunkArr.length-1]
          if(lastC[0]==='r'){
            lastC[4]=lastC[4]+1;
            lastC[1]=s2.substr(lastC[3],lastC[4])
          }else{
            chunkArr.push(['r',s2.substr(n2,1),n1,n2,1])
          }
          n1=n1+1;
          n2=n2+1;
        }
      }

    }
  }
  if(n1<n){
    // chunkArr.push(['d',n1,n-n1,s1.substr(n1,n-n1)])
  }
  if(n2<m){
    chunkArr.push(['a',s2.substr(n2,m-n2),n1,n2,m-n2])
  }
  return chunkArr;
}

//执行增量包
function execChunk(s1,chunk){
  var ns=''
  for(let i=0;i<chunk.length;i++){
    const arr=chunk[i];
    if(arr[0]==='e'){
      ns=ns+s1.substr(arr[1],arr[2])
    }else if(arr[0]==='r'){
      ns=ns+arr[1]
    }else if(arr[0]==='a'){
      ns=ns+arr[1]
    }
  }
  return ns
}


const chunk=makeChunk(s1,s2);
console.log(chunk)
const nstr=execChunk(s1,chunk)
console.log(nstr,nstr===s2)

猜你喜欢

转载自www.cnblogs.com/caoke/p/11571875.html
今日推荐