字符串匹配的后缀数组的直接比较和利用rank[i]=k的倍增法

2023-05-16

public static Suff[] getSa(String s)
    {    
        Suff [] SuffArrays = new Suff[s.length()];
        //sa[i]=k表明的排名为i的后缀是从k开始的
        for(int i=0;i<s.length();i++)
        {
            SuffArrays[i]=new Suff(s.substring(i),i);//substring(i)代表从起始位置到结束
        }
        Arrays.sort(SuffArrays);//对数组按照字典顺序排序
        return SuffArrays;
    }
    //用二分法去匹配Suff数组中的匹配数组
        public static void match() //
        {
            String s ="AABABABABB";
            String p = "BABB";
            //Suff [] sa = getSa(s);
            Suff [] sa = getSa2(s);
            int l = 0;
            int r =s.length()-1;
            while(r>=l)
            {
                int mid = l+((r-l)>>1);
                Suff midsuff = sa[mid];
                String suffStr = midsuff.str;//中间字符串
                ///(防止遗漏)int compares 后缀串和模式串比较结果,分为长度是否大于或者长度小于等
                int compares;
                if(suffStr.length()>=p.length())
                {
                    compares = suffStr.substring(0, p.length()).compareTo(p);
                }
                else
                {
                    compares = suffStr.compareTo(p);
                }
                if(compares>0)
                {
                    r=mid-1;
                }
                else if(compares<0)
                {
                    l = mid+1;
                }
                else
                {
                    System.out.print(midsuff.index);
                    break;
                }
                
            }
                    
        }
        /**
         * 思路:1,构造suffaryy数组,利用rank[i]=k的信息进行比较
         * 而不是字符串的比较进行。
         * 如果出现是一个字符的话,直接排序
         * 如果出现2,4,8.。。。等倍增的字符时候,
         * 先判断rank[i]与rank[j]是否是相同,
         * 不同则直接返回rank[i]-rank[j]比较规则,
         * 如果相同的话就则比较rank[i+k/2]-rank[j+k/2]
         * 外层是logn趟,里面是nlgn排序所以总的排序是nlg的平方,
         *k=1,一个字符,得到了sa,rk。
         *k=2,利用上一轮的rk快速比较两个后缀
         * k=4...
         */
        public static Suff [] getSa2(String sc)
        {
            int length = sc.length();
            final int rk[] = new int[length];
            Suff[] suffA = new Suff[length];
            for(int k =1;k<=length;k=k*2)//k也可以等于length,k代表截取范围,刚开始截取一个字符,而后是两个字符,,,,
            {
                for(int i=0;i<length;i++)
                {
                    String suff = sc.substring(i, i+k>length?length:i+k);
                    suffA[i] = new Suff(suff,i);
                    
                }
                
            if(k==1)//一个字符,直接进行排序
            {
                Arrays.sort(suffA);//nlogn
            }
            else
            {     final int kk=k;
                 Arrays.sort(suffA, new Comparator<Suff>(){
                     //不是基于字符串比较,而是用之前的rank
                     @Override
                     public int compare(Suff o1, Suff o2)
                     {
                         int i=o1.index;
                         int j=o2.index;
                         if(rk[i]==rk[j])
                         {
                             try
                             {
                                 return rk[i+kk/2] - rk[j+kk/2];//用个好的变量kk
                             }catch (ArrayIndexOutOfBoundsException e) //数组越界异常对象为e
                             {
                                 return o1.str.length()-o2.str.length();
                             }
                         }
                         else //如果第一个不等直接返回差值
                         {
                             return rk[i]-rk[j];
                         } 
                     }
                     
                 });
            }
            //排序完成后产生rank,给定下标,产生排名
            int r=0;
            rk[suffA[0].index] =r;
            for (int i=0;i<length;i++)
            {
                if(suffA[i].compareTo(suffA[i-1])==0)
                {
                    rk[suffA[i].index]=r;
                }
                else
                {
                    rk[suffA[i].index]=++r;
                }
            }
            }
            return suffA;
            
        }

**
 * 
 * 后缀数组的实现类
 *思路1,构造后缀数组,按照字符串的从小到大的字典顺序排列,数组的内容按照字符串+原始序列排序
 */
class Suff implements Comparable<Suff>{


    String str;//后缀字符串内容
    int index;//后缀的起始下标
    
    public Suff(String str, int index)
    {
        this.str = str;
        this.index = index;
    }
    @Override
    public int compareTo(Suff o2) {
        return this.str.compareTo(o2.str);
    }
    @Override
    public String toString()
    {
        return "Suff{"+
            "str="+str+'\''+
            ", index"+index+
            '}';
    }
    
}
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串匹配的后缀数组的直接比较和利用rank[i]=k的倍增法 的相关文章

随机推荐

  • Jupyter Notebook添加代码自动补全功能的方法

    Jupyter Notebook成为一款非常受欢迎的交互式Python运行环境的软件 通过如下的方法可以添加代码自动补全的功能 输入命令安装插件 pip3 install jupyter contrib nbextensions 然后运行
  • 修改grub默认启动选项的方法

    在Windows系统基础上 xff0c 再安装Linux xff0c 形成双系统 这样在grub启动菜单中会包含Linux Windows等多个选项 xff0c 默认为第一个选项 xff0c 常规的Linux启动 通过修改配置文件 etc
  • 在云服务器上搭建Jupyter Notebook服务

    Jupyter Notebook提供了远程登录的功能 xff0c 可以在云服务器上配置Jupyter Notebook xff0c 用户可以远程登录和运行Python代码 这里使用的是腾讯云的Ubuntu服务器 xff0c 配置方法如下 1
  • 常用Linux命令

    记录一些常用的Linux命令 1 用户管理 增加用户 useradd lt user name gt useradd g lt group name gt lt user name gt g选项指定新用户所属的用户组 修改用户的组别 use
  • 在云服务器上安装VNC远程桌面服务

    云服务器操作系统通常不包含图形界面 xff0c 通过在服务器上安装VNC服务 xff0c 可以让用户以图形化界面远程登录到云服务器 这里服务器使用的是Ubuntu Server 18 04系统 1 安装图形界面 首先在服务器端安装图形化桌面
  • 【Android】ADB无线连接Android设备

    目录 简介无线连接的条件adb连接设备方法一方法二 修改端口号方法一方法二 辅助工具android toolscrcpy gui 问题集合 简介 Android Debug Bridge xff0c 简称adb xff0c 是一种功能多样的
  • 人工智能学习:载入MNIST数据集(1)

    MNIST数据集是人工智能学习入门的数据集 xff0c 包含了一系列的手写的数字图片 载入MNIST数据集的方法很简单 xff0c Tensorflow集成了载入数据集的方法 首先导入tensorflow模块和matplotlib pypl
  • 人工智能学习:MNIST数据分类识别神经网络(2)

    在MNIST数据集上构建一个神经网络 xff0c 进行训练 xff0c 以达到良好的识别效果 1 导入模块 首先 xff0c 导入必要的模块 span class token keyword import span numpy span c
  • 人工智能学习:NMIST数据分类识别-CNN网络(3)

    这里采用CNN模型 xff08 卷积神经网络 xff09 来进行MNIST数据集的分类识别 1 导入模块 首先 xff0c 导入需要的模块 span class token keyword import span numpy span cl
  • 人工智能学习:CIFAR-10数据分类识别(4)

    与MNIST类似 xff0c CIFAR 10同样是人工智能学习入门的数据集之一 xff0c 它包含飞机 汽车 小鸟等10个类别的图片 xff0c 一共60000张图片 xff0c 其中训练集占50000张 xff0c 测试集占10000张
  • 人工智能学习:CIFAR-10数据分类识别-VGG网络(5)

    这里尝试采用VGG网络对CIFAR 10数据集进行分类识别 1 导入需要的模块 span class token keyword import span numpy span class token keyword as span np s
  • 人工智能学习:PASCAL VOC数据集读取(6)

    PASCAL VOC是一个国际的计算机视觉挑战赛 xff0c 数据集包含了20个分类的3万多张图片 挑战赛及其数据集基础上涌现不少知名的目标检测模型如R CNN xff0c YOLO xff0c SSD等 可以通过下载和读取的方法载入PAS
  • 人工智能学习:Microsoft COCO数据集读取(7)

    Microsoft COCO xff08 Common Objects in Context xff09 是微软研发维护的一个大型的数据集 包含了30多万张图片和91个目标分类 可用于目标识别 xff08 Object Detection
  • 人工智能学习:ResNet神经网络(8)

    ResNet是一种非常有效的图像分类识别的模型 xff0c 可以参考如下的链接 https blog csdn net qq 45649076 article details 120494328 ResNet网络由残差 xff08 Resi
  • 人工智能学习:倒立摆(CartPole)(9)

    倒立摆是强化学习的一个经典模拟对象 xff0c 通过对倒立摆对象的持续的动作输入 xff0c 使倒立摆保持在竖立的状态或者倒下 Python提供了一个模拟库 xff08 gym xff09 来模拟倒立摆等一些典型的难度控制对象 首先载入gy
  • 理解卡尔曼滤波

    卡尔曼滤波被广泛的应用于运动估计中 xff0c 在飞行器中多有应用 xff0c 区别于普通滤波如低通滤波 xff0c 卡尔曼滤波具有不延时的优点 xff0c 即普通的低通滤波在过滤噪声的同时也会引入信号滞后 xff0c 而卡尔曼滤波则可以实
  • 【Kotlin】Kotlin函数那么多,你会几个?

    目录 标准函数letrunwithapplyalsotakeIftakeUnlessrepeat小结作用域函数的区别作用域函数使用场景 简化函数尾递归函数 xff08 tailrec xff09 扩展函数高阶函数内联函数 xff08 inl
  • 2021-02-13

    昨天学习了关于位运算的一些常识 xff0c 自己也跟着视频敲了一些位运算代码如下 xff1a package com raisecom tiap ems basic mgt domain acl import java util Array
  • 字符串匹配中KMP算法的next数组构造与思考

    对于KMP算法的next算法 xff0c 匹配规则i不动 xff0c j而是根据 next j 61 k 如果在j位置失配 xff0c 则退到k位置 构造next数组的 是根据前缀与后缀的最长匹配 如ababaa 的next数组是 1001
  • 字符串匹配的后缀数组的直接比较和利用rank[i]=k的倍增法

    public static Suff getSa String s Suff SuffArrays 61 new Suff s length sa i 61 k表明的排名为i的后缀是从k开始的 for int i 61 0 i lt s l