• 【洛谷P3809】【模板】后缀排序


    题目

    题目链接:https://www.luogu.com.cn/problem/P3809
    读入一个长度为 (n) 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 (1)(n)

    思路

    倍增求 SA 数组。
    推荐 Blog 或者蓝书。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1000010;
    int n,m,x[N],y[N],sa[N],c[N];
    char ch[N];
    
    void SA()
    {
    	for (int i=1;i<=n;i++) x[i]=ch[i],c[x[i]]++;
    	for (int i=2;i<=m;i++) c[i]+=c[i-1];
    	for (int i=n;i>=1;i--) sa[c[x[i]]--]=i;
    	for (int k=1;k<=n;k<<=1)
    	{
    		int num=0;
    		for (int i=n-k+1;i<=n;i++) y[++num]=i;
    		for (int i=1;i<=n;i++) if (sa[i]>k) y[++num]=sa[i]-k;
    		for (int i=1;i<=m;i++) c[i]=0;
    		for (int i=1;i<=n;i++) c[x[i]]++;
    		for (int i=2;i<=m;i++) c[i]+=c[i-1];
    		for (int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
    		swap(x,y);
    		x[sa[1]]=1; num=1;
    		for (int i=2;i<=n;i++)
    			x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num;
    		m=num;
    		if (m==n) break;
    	}
    }
    
    int main()
    {
    	scanf("%s",ch+1);
    	n=strlen(ch+1); m=122;
    	SA();
    	for (int i=1;i<=n;i++)
    		printf("%d ",sa[i]);
    	return 0;
    }
    
  • 相关阅读:
    mysql安装及初始密码问题
    centos7上安装erlang22.1
    共享文件夹设置
    putty免密登录
    重新开始
    单任务多线程 安全
    线程池
    多线程
    commons-IO
    打印流
  • 原文地址:https://www.cnblogs.com/stoorz/p/13821581.html
Copyright © 2020-2023  润新知