Niuke Challenge 39 suffix array of password system

LINK: Password system

It is easy to find that there are a total of k different divisions, and in each division we require the one with the largest lexicographical order and then compare with the others to find the smallest lexicographical order.

First consider how to find the largest one. This is a lexicographical problem. Find the sa array and then scan backwards to segment. If you want to segment it, press i% k points.

After finding the largest one, consider how to find the smallest one. It is easy to find or sa array to look at the inevitable lexicographic order between them.

It is worth mentioning that although the suffix array is difficult to write, the idea is very good. It is not easy to write wrongly according to the idea instead of relying on a hard back.

//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ldb long double
#define pb push_back
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define pii pair<int,int> 
#define mk make_pair
#define RE register
#define P 1000000007
#define S second
#define F first
#define mod 998244353
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define ull unsigned long long
#define ui unsigned
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
const int MAXN=1000010<<1;
int n,m,k;
char a[MAXN];int vis[MAXN];
int c[MAXN],x[MAXN],y[MAXN],sa[MAXN],rk[MAXN],h[MAXN];
inline void SA()
{
	m=150;
	rep(1,n,i)++c[x[i]=a[i]];
	rep(1,m,i)c[i]+=c[i-1];
	rep(1,n,i)sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k=k<<1)
	{
		int num=0;
		rep(n-k+1,n,i)y[++num]=i;
		rep(1,n,i)if(sa[i]>k)y[++num]=sa[i]-k;
		rep(1,m,i)c[i]=0;
		rep(1,n,i)++c[x[i]];
		rep(1,m,i)c[i]+=c[i-1];
		fep(n,1,i)sa[c[x[y[i]]]--]=y[i];
		rep(1,n,i)y[i]=x[i],x[i]=0;
		x[sa[1]]=num=1;
		rep(2,n,i)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?num:++num;
		if(num==n)break;
		m=num;
	}
	rep(1,n,i)rk[sa[i]]=i;
}
inline void get_H()
{
	int k=0;
	rep(1,n,i)
	{
		if(rk[i]==1)continue;
		if(k)--k;
		int j=sa[rk[i]-1];
		while(a[i+k]==a[j+k])++k;
		h[rk[i]]=k;
	}
}
int main()
{
	//freopen("1.in","r",stdin);
	gt(n);gt(k);gc(a);
	rep(1,n,i)a[i+n]=a[i];
	n=n<<1;SA();get_H();
	//rep(1,n,i)put(rk[i]);
	int en=k+n/2-1,st;//有效部分.
	fep(n,1,i)
	{
		if(sa[i]>en)continue;
		int ww=sa[i]%k;
		if(vis[ww])continue;
		vis[ww]=1;st=i;
	}
	rep(sa[st],sa[st]+k-1,i)putchar(a[i]);
	return 0;
}

Guess you like

Origin www.cnblogs.com/chdy/p/12745883.html