zoukankan      html  css  js  c++  java
  • 后缀数组SA超详细讲解

    (标题是用来钓鱼的<( ̄3 ̄)> )

      重新回顾了一下SA的板子,感觉理解得更深了。细节看码。

    #include <bits/stdc++.h>
    
    #define rep(i, a, b) for (int i = a, i##end = b; i <= i##end; ++i)
    #define per(i, a, b) for (int i = a, i##end = b; i >= i##end; --i)
    #define rep0(i, a) for (int i = 0, i##end = a; i < i##end; ++i)
    #define per0(i, a) for (int i = a-1; ~i; --i)
    #define chkmin(a, b) a = std::min(a, b)
    #define chkmax(a, b) a = std::max(a, b)
    
    typedef long long ll;
    
    const int maxn = 1111111;
    
    char s[maxn];
    int sa[maxn];
    
    void build_sa(char *s, int *sa) {
    	static int t[maxn << 1], t2[maxn << 1], c[maxn], *x, *y, n, m;
        // t,t2是两个数组(要开两倍,否则下面比较会溢出),x和y将会指向它们;c是基数排序的桶;n表示长度,m表示字符集大小
    	x = t, y = t2, n = strlen(s), m = 'z'+1;
        // 往下,x存第一关键字的值
    	rep0(i, m) c[i] = 0; // 清空桶
    	rep0(i, n) c[x[i] = s[i]]++; // 将字符串转化到x数组中(初始情况下第一关键字即为单个字符)并放入桶中
    	rep(i, 1, m-1) c[i] += c[i-1]; // 前缀累加可以方便查询排名
    	per0(i, n) sa[--c[x[i]]] = i; // 把后缀按照排名(此时长度为1)放入后缀数组中,注意要倒过来,保证串短的在前
    	for (int k = 1; k < n; k <<= 1) { // 倍增(长度为2k)
    		int p = 0; // 一变量多用。用来当y数组的指针;之后表示新的字符集大小
    		rep(i, n-k, n-1) y[p++] = i; // 第二关键字为Φ的后缀位置先排
    		rep0(i, n) if (sa[i] >= k) y[p++] = sa[i]-k;
            // 用sa来排第二关键字(不存在第二关键字为<k的位置)
    		rep0(i, m) c[i] = 0; // 跟前面类似
    		rep0(i, n) c[x[y[i]]]++;
    		rep(i, 1, m-1) c[i] += c[i-1];
    		per0(i, n) sa[--c[x[y[i]]]] = y[i];
            // 注意一定要倒过来取排名,保证第二关键字排序结果正序
    		std::swap(x, y); // 快速交换数组(指针)
    		p = 1, x[sa[0]] = 0; // 安排排名第一的权值
    		rep(i, 1, n-1)
    			x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k] ? p-1 : p++;
            // 比对第一关键字和第二关键字
    		if ((m = p) == n) return; // 如果字符集=n,显然没有必要再排了
    	}
    }
    
    int main() {
    	scanf("%s", s);
    	build_sa(s, sa);
    	rep0(i, strlen(s)) printf("%d ", sa[i]+1);
    	return 0;
    }
    
  • 相关阅读:
    写给刚接触Active Directory的朋友(转)
    vim中缩进的设置以及将tab转换成空格
    Ubuntu12.04 更新源
    实验三电子公文传输系统1个人贡献
    20191325实验四 Web服务器1socket编程
    20191325学习笔记10
    OpenEuler 中C与汇编的混合编程
    20191325第十三章学习笔记
    20191323第十四章学习笔记
    http 三次握手 四次挥手,面试题
  • 原文地址:https://www.cnblogs.com/ac-evil/p/12891355.html
Copyright © 2011-2022 走看看