zoukankan      html  css  js  c++  java
  • LG P3809 【模板】后缀排序

    贴模板

    注意:( ext{id}) 表示第二关键字排序后(其实无需排序,利用上轮的 ( ext{sa}) 值即可)相应的第一关键字的位置
    计数排序为了稳定性最后确定位置时要倒着开始
    复制的 ( ext{ork}) 要开两倍

    ( ext{Code})

    #include <cstdio>
    #include <cstring>
    #define re register
    using namespace std;
    
    const int N = 1e6 + 5;
    int n, sa[N], rk[N], cnt[N], id[N], ork[N << 1];
    char s[N];
    
    inline int comp(int x, int y, int w){return (ork[x] == ork[y]) && (ork[x + w] == ork[y + w]);}
    
    inline void build_SA()
    {
    	int m = 300, p;
    	for(re int i = 1; i <= n; i++) ++cnt[rk[i] = s[i]];
    	for(re int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
    	for(re int i = n; i; i--) sa[cnt[rk[i]]--] = i;
    	
    	for(re int w = 1; w < n; w <<= 1, m = p)
    	{
    		p = 0;
    		for(re int i = n - w + 1; i <= n; i++) id[++p] = i;
    		for(re int i = 1; i <= n; i++)
    		if (sa[i] > w) id[++p] = sa[i] - w;
    		
    		for(re int i = 0; i <= m; i++) cnt[i] = 0;
    		for(re int i = 1; i <= n; i++) ++cnt[rk[id[i]]];
    		for(re int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
    		for(re int i = n; i; i--) sa[cnt[rk[id[i]]]--] = id[i];
    		
    		for(re int i = 1; i <= n; i++) ork[i] = rk[i];
    		p = 0;
    		for(re int i = 1; i <= n; i++)
    		rk[sa[i]] = comp(sa[i], sa[i - 1], w) ? p : ++p;
    		if (p >= n) break;
    	}
    }
    
    int main()
    {
    	scanf("%s", s + 1), n = strlen(s + 1), build_SA();
    	for(re int i = 1; i <= n; i++) printf("%d ", sa[i]);
    }
    
  • 相关阅读:
    shell
    regionMatches方法
    ==
    使用INTO子句创建新表
    数据库除运算
    数据库笛卡尔积运算
    人生格言
    刚开通~
    Nginx:413 Request Entity Too Large
    ORACLE 查看并修改最大连接数
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15138906.html
Copyright © 2011-2022 走看看