zoukankan      html  css  js  c++  java
  • 洛谷4051 JSOI2007 字符加密(SA)

    真是一道良好的SA模板题

    首先,由于涉及到从左边移动到右边这个过程,我们不妨直接把字符串复制一遍,接在后面。
    然后直接构造后缀数组,按排名从小到大,枚举所有的位置,如果这个后缀的起始点是在原串中的,那么就输出当前后缀的起始点往后第n个字符,就能直接解决了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define mk makr_pair
    #define ll long long
    using namespace std;
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    const int maxn = 2e6+1e2;
    int rk[maxn],wb[maxn],sa[maxn];
    int tmp[maxn],h[maxn],height[maxn];
    int n;
    char a[maxn];
    void getsa()
    {
     int *x =rk,*y=tmp;
     int s = 128;
     for (int i=1;i<=n;i++) x[i]=a[i],y[i]=i;
     for (int i=1;i<=s;i++) wb[i]=0;
     for (int i=1;i<=n;i++) wb[x[y[i]]]++;
     for (int i=1;i<=s;i++) wb[i]+=wb[i-1];
     for (int i=n;i>=1;i--) sa[wb[x[y[i]]]--]=y[i];
     int p =0;
     for (int j=1;p<n;j<<=1)
     {
      p=0;
      for (int i=n-j+1;i<=n;i++) y[++p]=i;
      for (int i=1;i<=n;i++) if (sa[i]>j) y[++p] = sa[i]-j;
      for (int i=1;i<=s;i++) wb[i]=0;
      for (int i=1;i<=n;i++) wb[x[y[i]]]++;
      for (int i=1;i<=s;i++) wb[i]+=wb[i-1];
         for (int i=n;i>=1;i--) sa[wb[x[y[i]]]--]=y[i];
      swap(x,y);
      p=1;
      x[sa[1]]=1;
      for (int i=2;i<=n;i++)
      {
       x[sa[i]] = (y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j]) ? p : ++p; 
       } 
       s=p;
     }
     for (int i=1;i<=n;i++) rk[sa[i]]=i;
     h[0]=0;
        for (int i=1;i<=n;i++)
     {
      h[i]=max(h[i-1]-1,0);
      while(i+h[i]<=n && sa[rk[i]-1]+h[i]<=n && a[i+h[i]]==a[sa[rk[i]-1]+h[i]]) h[i]++;
     } 
     for (int i=1;i<=n;i++) height[i]=h[sa[i]];
    }
    int main()
    {
      scanf("%s",a+1);
      n=strlen(a+1);
      for (int i=1;i<=n;i++) a[i+n]=a[i];
      n*=2;
      getsa();
      for (int i=1;i<=n;i++)
      {
       if (sa[i]<=n/2) cout<<a[sa[i]+n/2-1];
      }
      return 0;
    }
    
    
  • 相关阅读:
    wso2使用
    wso2安装
    CLR 编译函数的两种结果的原因
    hduoj4311
    通过Git在本地局域网中的两台电脑间同步代码
    Git基本操作之强制推送覆盖仓库
    设置Mac共享网络给其他设备
    谷歌浏览器设置无图浏览模式
    加载到SGA中的库缓存对象超过阈值
    webBrowser 禁止屏蔽alert confirm open showModalDialog
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161972.html
Copyright © 2011-2022 走看看