• 后缀数组学习笔记


    后缀数组与AC自动机的区别:后缀数组对文本串预处理,而AC自动机对匹配串处理

    过程

    假定文本串为BANANA,在它的末尾添加一个字符'$'(可以是任意一个未在串中出现过的字符),然后将它的所有后缀(BANANA$,ANANA$,NANA$,ANA$,NA$,A$)插到一棵(trie)中. 由于添加了尾字符'$',因此(trie)中的每一个叶节点唯一对应字符串中的一个后缀.

    在绘制(trie)的过程中,对于每一个结点,我们将它的子节点按照字典序排好,字典序大的在右边,小的在左边,$规定为最小的字符,然后在叶节点中标上该结点对应后缀的第一个字符的下标(在这里默认字符串中第一个字符的下标为0),然后自左向右地将叶子的编号排出来,就得到了后缀数组(SA).
    字符串BANANA$SA={5,3,1,0,4,2}

    那么怎么得到这个数组呢?我们采用Manber和Myers发明的倍增法:
    首先,将所有字符排序,计算出每个字符的名次,最小的字母是第一名,次小的字母是第二名,以此类推.
    例如字符串aabaaaab,对应着数组{1,1,2,1,1,1,1,2}

    然后给所有后缀的前两个字符排序
    对于aabaaaab来说,就是给{aa,ab,ba,aa,aa,aa,ab,b_}排序,等价于给二元组{11,12,21,11,11,11,12,20}排序
    如果你没做错,你会得到{1,2,4,1,1,1,2,3}

    下面给所有后缀的前四个字符排序,这等价于给数组{14,21,41,11,12,13,20,30}排序
    不难发现,因为s.substr(k,4)=s.substr(k,2)+s.substr(k+2,2),因此只要将第(k)个数拼上第(k+2)个数,就是我们想要的数组
    这一步排完序后,我们得到{4,6,8,1,2,3,5,7}

    最后,我们给所有后缀的前8个字符排序,得到{4,6,8,1,2,3,5,7}
    机智的你或许一经发现,这一步排完之后,和上一步排完之后得到一样的结果,为什么呢?因为上一步的结果中,所有的数已经互不相同,这时候再将第(k)个数加上第(k+4)个数时,由于前面一位互不相同,已经可以将所有数排好序,所以结果不会改变

    下面来看看它的时间复杂度.由于每次长度翻倍,最多进行(logn)次排序,每次可以使用一些例如基数排序之类的算法,将排序复杂度降为(O(n)),所以总的复杂度为(O(nlogn)).

    下面是构建SA的代码:

    char s[MAXN];
    int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
    
    void build_sa(int m){
    	int i,*x=t,*y=t2;
    	
    	for(i=0;i<m;i++) c[i]=0;
    	for(i=0;i<n;i++) c[x[i]=s[i]]++;
    	for(i=1;i<m;i++) c[i]+=c[i-1];
    	for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    	
    	for(int k=1;k<=n;k<<=1){
    		int p=0;
    		for(i=n-k;i<n;i++) y[p++]=i;
    		for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
    		for(i=0;i<m;i++) c[i]=0;
    		for(i=0;i<n;i++) c[x[y[i]]]++;
    		for(i=0;i<m;i++) c[i]+=c[i-1];
    		for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
    		
    		swap(x,y);
    		p=1;x[sa[0]]=0;
    		for(i=1;i<n;i++)
    			x[sa[i]=(y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k])?p-1:p++;
    		if(p>=n) break;
    		m=p;
    	}
    }
    
  • 相关阅读:
    Features for Multi-Target Multi-Camera Tracking and Re-identification论文解读
    CBAM(Convolutional Block Attention Module)使用指南
    j2ee web项目 ssh 中使用junit测试
    log4j 发送日志到邮箱
    java.util.ConcurrentModificationException
    java 项目 报错
    json 传参数到action中 乱码
    TOMCAT 信息
    action 纯注解 笔记
    java 上传图片 打水印
  • 原文地址:https://www.cnblogs.com/nflslzt/p/8746320.html
Copyright © 2020-2023  润新知