【模板】SA数组--sa[]与rk[]求解(height[]被我咕掉了)

一. 计数排序优化 O(nlogn)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int n,m;
char s[N];
int sa[N],rk[N],cnt[200],oldrk[N],oldsa[N];
int main() {
	scanf("%s",s+1);
	n=strlen(s+1);
	m=128;
	
	for(int i=1;i<=n;i++) cnt[rk[i]=s[i]]++;
	for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
	for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
	
	for(int w=1,q;w<n;w++,m=q) {
		int cur=0;
		for(int i=n-w+1;i<=n;i++) oldsa[++cur]=i;
		for(int i=1;i<=n;i++) {
			if(sa[i]>w) oldsa[++cur]=sa[i]-w;
		}
		
		memset(cnt,0,sizeof cnt);
		for(int i=1;i<=n;i++) cnt[rk[i]]++;
		for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
		for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=oldsa[i];
		
		q=0;
		memcpy(oldrk,rk,sizeof rk);
		for(int i=1;i<=n;i++) {
			if(oldrk[sa[i]]==oldrk[sa[i-1]] && 
				oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) {
				rk[sa[i]]=q;		
			}
			else {
				rk[sa[i]]=++q;
			}
		}
		if(q==n) break;
	}
        for(int i=1;i<=n;i++) printf("%d ",sa[i]);
	return 0;
}

二. 快排优化 O(n^2 logn)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int n,w;                         //lambda 要捕获w, 我们需要将w作为全局变量
char s[N];
int sa[N],rk[N],oldrk[N];
int main() {
	scanf("%s",s+1);
	n=strlen(s+1);
	
	for(int i=1;i<=n;i++) sa[i]=i,rk[i]=s[i];
	
	int q;
	for(w=1;w<n;w++) {
		sort(sa+1,sa+1+n,[](int x,int y){
			return (rk[x]==rk[y])?rk[x+w]<rk[y+w]:rk[x]<rk[y];
		});
		
		q=0;
		memcpy(oldrk,rk,sizeof rk);
		for(int i=1;i<=n;i++) {
			if(oldrk[sa[i]]==oldrk[sa[i-1]] && 
				oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) {
				rk[sa[i]]=q;		
			}
			else {
				rk[sa[i]]=++q;
			}
		}
		if(q==n) break;
	}
	
	for(int i=1;i<=1;i++) printf("%d ",sa[i]);
	return 0;
}
posted on 2024-11-22 23:14  Ueesugi_sakura  阅读(4)  评论(0编辑  收藏  举报