zoukankan      html  css  js  c++  java
  • 后缀数组、名次数组-JavaScript

    后缀数组sa,告诉你,排第几的是谁

    名次数组rank, 告诉你,你排第几

    height数组,i为排名,排名为i的后缀为sa[i]

    height[i]表示后缀sa[i]和sa[i-1]的最长公共前缀的长度n

    //二分查找法,返回最接近的位置和实际位置
    function binary_find(id,hasSortArr){
    let l=0,r=hasSortArr.length;
    let index=-1;
    while(r-l>0){
    const m=(l+r)>>1;
    const mid=hasSortArr[m]
    //比较下坐标大小
    const order=id>mid?1:(id<mid?-1:0)

    if(order===1){
    l=Math.max(l+1,m)
    }else if(order===-1){
    r=Math.min(r-1,m)
    }else{
    l=r=m;
    index=m;
    }
    }
    return [(l+r)>>1,index]
    }
    //二分法去重排序
    function binary_sort(str) {
    const sa=[]
    for(let i=0;i<str.length;i++){
    const [n,index]=binary_find(str[i],sa);
    if(index===-1){
    sa.splice(n,0,str[i])
    }
    }
    return sa;
    }

    //后缀数组sa,告诉你,排第几的是谁
    //名次数组rk, 告诉你,你排第几
    //SA[i]表示排名为i的后缀、rk[i]表示起始位置的下标为i的后缀的排名
    ////获取后缀数组
    function getSa(str) {
    let arr=str.split('');
    const sLen=arr.length;//总共排名长度
    let uarr=binary_sort(arr);//获取排序去重后的
    const rk=[];
    let run=true;
    let len=1;//最长相似字符
    while (run){
    const map={}
    uarr.forEach(function (v,k) {
    map[v]=k+1;
    })
    for(let i=0;i<sLen;i++){
    rk[i]=map[arr[i]];
    }
    if(uarr.length<sLen){
    for(let i=0;i<sLen;i++){
    const fz=i+len<sLen?rk[i+len]:0;
    arr[i]=rk[i]*(uarr.length+1)+fz;
    }
    len=len*2;
    uarr=binary_sort(arr)
    }else{
    run=false;
    }
    }
    //SA[i]表示排名为i的后缀、rk[i]表示起始位置的下标为i的后缀的排名
    const sa=[]
    rk.forEach(function (v,k) {
    sa[v-1]=k;
    })
    return sa
    }
    //SA[i]表示排名为i的后缀
    function getRkBySa(sa){
    const rk=[]
    sa.forEach(function (v,k) {
    rk[v]=k;
    })
    return rk;
    }
    //height[i] 表示排名为i的公共前缀长度
    //h[i] 表示起始位置的下标为i的公共前缀长度
    function calheight(s,rk,sa) {
    const h=[];
    const height=[];
    for (let i=0;i<s.length;i++){
    let k=0;
    if(rk[i]>0){
    const j=sa[rk[i]-1]
    while (s[i+k]===s[j+k]){
    k++
    }
    }
    height[rk[i]]=k;
    h[i]=k
    }

    return {height,h};
    }

    //demo
    const str1='* 4444222233323333';
    ////获取后缀数组
    const sa=getSa(str1);
    const rk=getRkBySa(sa);
    const {height,h}=calheight(str1,rk,sa)
    console.log(sa,rk,height,h)

     //输出

    [
    1, 0, 6, 7, 8, 9, 13,
    17, 12, 16, 11, 15, 10, 14,
    5, 4, 3, 2
    ] [
    1, 0, 17, 16, 15, 14, 2,
    3, 4, 5, 12, 10, 8, 6,
    13, 11, 9, 7
    ] [
    0, 0, 0, 3, 2, 1, 4,
    0, 1, 1, 2, 2, 3, 3,
    0, 1, 2, 3
    ] [
    0, 0, 3, 2, 1, 0, 0,
    3, 2, 1, 3, 2, 1, 4,
    3, 2, 1, 0
    ]

  • 相关阅读:
    css子元素水平垂直居中
    js 防抖节流
    NOIP 游记
    flash player播放器用法
    android设备连接不上电脑的解决方法
    AndroidStudio自动下载gradle失败问题解决
    3组Alpha冲刺5/6
    3组Beta冲刺2/5
    3组Beta冲刺5/5
    3组Beta冲刺1/5
  • 原文地址:https://www.cnblogs.com/caoke/p/13195253.html
Copyright © 2011-2022 走看看