zoukankan      html  css  js  c++  java
  • 后缀数组[学习笔记]

    后缀数组[学习笔记]

    这几天打算系统地学习一下字符串有关的东西...

    今天看了看国家集训队的论文,做了几道板子题,感觉还是很有收获的,也算稍微把后缀数组的坑填了一下吧。

    倍增算法求SA数组

    利用倍增的思想来求后缀数组。

    方法大概就是用基数排序,第一次按照每个后缀开头的字符为关键字,排一遍序,得到第一遍的rank。然后扩展到以开头两个字符再排序,这两个字符分别用上一次他们的rank,两个关键字进行基数排序。然后长度再乘2,扩展到4个...就这样一直扩展直到没有两个后缀排名相等就好了

    代码以及注释

    int n,h[maxn],sa[maxn],rk[maxn],tax[maxn],tp[maxn],m;
    char s[maxn];
    void Qsort(){
        for(int i=0;i<=m;i++) tax[i]=0;
        for(int i=1;i<=n;i++) tax[rk[i]]++;//按照第一关键字划分得到每个桶的大小
        for(int i=1;i<=m;i++) tax[i]+=tax[i-1];//前缀和来得到每一组最后一位的排名
        for(int i=n;i>=1;i--)
            sa[tax[rk[tp[i]]]--]=tp[i];//第二关键字的桶尾--,填入元素
    }//基数排序,其中tp为第二关键字,rk为第一关键字
    void getsa(){
        m=126;//m为字符集大小
        for(int i=1;i<=n;i++)
            rk[i]=s[i]-'a',tp[i]=i;//得出第一次的rk和tp
        Qsort();//第一次排序
        for(int p=1,w=1;p<n;m=p,w<<=1){
            p=0;
            for(int i=1;i<=w;i++) tp[++p]=n+i-w;//对于最后w个,他们的第二关键字所在的位置已经
            for(int i=1;i<=n;i++)       //超过字符串长,第二关键字为空,字典序肯定是最小的
                if(sa[i]>w) tp[++p]=sa[i]-w;   //将自己的rk赋给位置减w的第二关键字
            Qsort();
            swap(rk,tp);//tp用不到了,用它来装上一次的rk
            rk[sa[1]]=p=1;
            for(int i=2;i<=n;i++)
                rk[sa[i]]=tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w]?p:++p;
    //上面是按照排名来划分rk,如果他和前一个的第一关键字第二关键字都相等则排名相等,否则rk++
        }
    }
    

    求height数组

    (height)数组的定义:(h[i])表示(rk)(i)的后缀与(rk)(i-1)的后缀的最长公共前缀,可以用(sa)数组和(rk)数组来(O(n))求得,这要用到一个性质:(h[rk[i]]>=h[rk[i-1]]-1)。也就是说如果根据(rk)从前往后求,每次暴力匹配来增加长度,结果是近似递增的,可以证明时间复杂度的正确性。性质的证明详见论文

    代码以及注释

    void geth(){
    		for(int i=1,j,k=0;i<=n;h[rk[i++]]=k)//i是要求的是第rk位,k为h数组的值
    		for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
        	//h[i]>=h[i-1]-1,k要--. 暴力匹配.
    }
    
  • 相关阅读:
    Spring Boot 属性配置和使用
    spring boot下WebSocket消息推送
    深入理解分布式事务,高并发下分布式事务的解决方案
    HashMap实现原理分析
    JVM 简述
    Java 并发之原子性与可见性
    Java 并发理论简述
    Java读取Properties文件的六种方法
    Java中的注解是如何工作的?
    XML解析——Java中XML的四种解析方式
  • 原文地址:https://www.cnblogs.com/nianheng/p/10035172.html
Copyright © 2011-2022 走看看