zoukankan      html  css  js  c++  java
  • 牛客挑战赛39 密码系统 后缀数组

    LINK:密码系统

    容易发现一共有k种不同的划分 而每种划分中我们要求出字典序最大的那个然后和其他的比较求出字典序最小的。

    先考虑如何求出最大的 容易发现这是字典序的问题 求出sa数组然后倒着扫描就行了 分段的话按i%k分即可。

    求出最大的了之后考虑如何求出最小的 容易发现还是sa数组看一下他们之间的相对位置 靠前的必然字典序要优。

    值得一提的是 后缀数组虽然难写 但是思想很好懂 按照思想来写不容易写错 而不是靠硬背。

    //#include<bitsstdc++.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
    ",x)
    #define putl(x) printf("%lld
    ",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;
    }
    
  • 相关阅读:
    逻辑卷管理LVM (Logical Volume Manager)
    Windows Server 2008 R2 域控修改域用户密码复杂性
    win7 加域开机自动登录域用户
    红帽Linux 配置VNC桌面远程工具
    Redhat linux 挂载命令mount
    SUSE Linux 防火墙设置
    IPv4 地址分类
    常用RAID简介_001
    Element UI
    ie中datepicker赋值不成功
  • 原文地址:https://www.cnblogs.com/chdy/p/12745883.html
Copyright © 2011-2022 走看看