LCSS算法实现-坐标系下的Scala版本

最近在使用用户的定位轨迹和公交车的行驶轨迹做匹配,查看用户是否在乘坐公交车,将每天内匹配的路径次数做特征,放入到模型分类之中,研究了一下LCSS算法的原理,参考文章如下, 之后在Scala版本下做了一个小型的测试,记录一下

https://blog.mythsman.com/post/5d3089bc976abc05b3454866/
https://blog.csdn.net/wk1134314305/article/details/78892155

Scala版本的代码如下

object Test {
  /**

  def main(args: Array[String]): Unit = {
    //设置字符串长度
    val substringLength1 = 20
    val substringLength2 = 20 //具体大小可自行设置

    val result = new StringBuffer

    // 随机生成字符串
    val x = GetRandomStrings(substringLength1)
    val y = GetRandomStrings(substringLength2)

    //val startTime = System.nanoTime
    // 构造二维数组记录子问题x[i]和y[i]的LCS的长度

    //val opt = new Array[Array[Int]](substringLength1 + 1,substringLength2 + 1)
    val opt = dimMatrixA(substringLength1 + 1,substringLength2 + 1)



    // 动态规划计算所有子问题
    for (i <- substringLength1 - 1 to 0 by -1) {
      for (j <- substringLength2 - 1 to 0 by -1) {
        if (x.charAt(i) == y.charAt(j)) opt(i)(j) = opt(i + 1)(j + 1) + 1 //参考上文我给的公式。
        else opt(i)(j) = Math.max(opt(i + 1)(j), opt(i)(j + 1))
      }
    }

    //println("substring1:" + x)
    //println("substring2:" + y)
    //println("LCS:")

    var i = 0
    var j = 0
    while ( {
      i < substringLength1 && j < substringLength2
    }) if (x.charAt(i) == y.charAt(j)) {
      //System.out.println(x.charAt(i))
      result.append(x.charAt(i))
      i += 1
      j += 1
    }
    else if (opt(i + 1)(j) >= opt(i)(j + 1)) i += 1
    else j += 1
    //val endTime = System.nanoTime
    //println(" Totle time is " + (endTime - startTime) + " ns")
    println("result:"+result)
  }


  def time(t:Int):String={
    val dt= DateTime.now().minusDays(t).toString("yyyyMMdd")
    dt
  }

  //取得定长随机字符串
  def GetRandomStrings(length: Int): String = {
    val buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyz")
    val sb = new StringBuffer
    val r = new Random
    val range = buffer.length
    for (i <- 0 until length) {
      sb.append(buffer.charAt(r.nextInt(range)))
    }
    sb.toString
  }
   */

  def dimMatrixA (a:Int,b:Int) = {
    val matrix = Array.ofDim[Int](a, b)
    matrix
  }

  //经纬度差值阈值大约0.001在地图上相差80-90米

  def main(args: Array[String]): Unit = {
    val coor1 = new Array[Coordinate](5)
    coor1(0) = new Coordinate(30.1, 114.300)
    coor1(1) = new Coordinate(30.101, 114.302)
    coor1(2) = new Coordinate(30.1002, 114.3023)
    coor1(3) = new Coordinate(30.1011, 114.30235)
    coor1(4) = new Coordinate(30.1003, 114.304)
    val coor2 = new Array[Coordinate](2)
    coor2(0) = new Coordinate(30.1002, 114.301)
    coor2(1) = new Coordinate(30.1015, 114.3023)
    val lcssMatrix=getTypeMatrix(coor1,coor2,0.001)//0。0002
    val lcssGen=genLCSS(coor1,coor2,0.001)
    val Ratio=lcssGen._2
    //val lcssRatio = getMatchRatio(coor1, coor2,0.0001)
    //for(i <- 0 until lcss._1.length){
    //  println(lcss._1(i))
    //}
    println(lcssMatrix._2)
    println(lcssGen._2)
    println(lcssGen._1.length)
    println(Ratio)
  }

  /**
   * 动态规划计算所有子问题
   *
   * @return
   */
  def getTypeMatrix(L1:Array[Coordinate],L2:Array[Coordinate],distThre:Double): (Array[Array[Int]],Int) = {
    val `type` = dimMatrixA(L1.length + 1, L2.length + 1)
    val comLen =  new ArrayBuffer[(Int)]
    for (i <- L1.length - 1 to 0 by -1) {
      for (j <- L2.length - 1 to 0 by -1) {
        if (isClose(L1(i), L2(j),distThre)) {
          //System.out.println(L1(i))
          //System.out.println(L2(j))
          `type`(i)(j) = `type`(i + 1)(j + 1) + 1
          comLen.append(1)
        }
        else `type`(i)(j) = Math.max(`type`(i)(j + 1), `type`(i + 1)(j))
      }
    }
    val commonLen=comLen.sum
    (`type`,commonLen)
  }

  /**
   * @return
   */
  def genLCSS(L1:Array[Coordinate],L2:Array[Coordinate],distThre:Double): (Array[Coordinate],Double) = {
      val typematrix = getTypeMatrix(L1,L2,distThre)
      val res = new Array[Coordinate](typematrix._2)
      var i = 0
      var j = 0
      var index = 0
      while ( {
        i < L1.length && j < L2.length
      }) if (isClose(L1(i), L2(j),distThre)) {
        //System.out.println(index)
        //System.out.println(i)
        //System.out.println(typematrix._2)
        //System.out.println(L1(i))
        //System.out.println(L2(j))
        res({
          index += 1; index - 1
        }) = L1(i)
        i += 1
        j += 1
      }
      else if (typematrix._1(i + 1)(j) >= typematrix._1(i)(j + 1)) i += 1
      else j += 1
      val LCS = res
      val matchRatio = LCS.length / Math.min(L1.length, L2.length).toDouble
      (res,matchRatio)
  }
  
    def isClose(p1: Coordinate, p2: Coordinate,distThre:Double): Boolean = {
      val x_abs = Math.abs(p1.getLatitude - p2.getLatitude)
      val y_abs = Math.abs(p1.getLongitude - p2.getLongitude)
      val res=if (x_abs < distThre && y_abs < distThre) {true}else{false}
      res
  }
}

你可能感兴趣的:(数据结构与算法)