• [JSOI2007]字符加密 后缀数组


    题面:洛谷

    题解:

      我们考虑,如果可以将环上每个长度为len的串都提取出来,再做个排序,那这题我们就做出来了!

      但是提取$n^2$,怎么办?

      考虑破环成链,再扩充为原来的2倍。

      然后直接做后缀排序,把长度大于len的串按排序结果顺次列下来,对于每个后缀取出前len个字符构成串,最后得到的就是我们要的排序结果。

      为什么这样是对的?

        假设我们的最终排序结果是S1, S2, S3, S4....Sn,我们在这些串后面乱加一些东西再排序并不会影响排序结果,因为字典序是要先比较前面的字符的,只有前面字符相同才会比较后面的字符。

        所以如果乱加的东西对串的排名产生了影响,那只能说明被改变了相对排名的这几个串,是相同的。

      这题就做完了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 405000
     5 
     6 int n, len, m = 127;
     7 int sa[AC], rk[AC], p1[AC], p2[AC], b[AC], d[AC];
     8 char s[AC];
     9 
    10 void pre()
    11 {
    12     scanf("%s", s + 1), len = strlen(s + 1), n = len << 1;
    13     for(R i = 1; i <= len; i ++) s[i + len] = s[i];
    14     for(R i = 1; i <= n; i ++) sa[i] = i, rk[i] = s[i];
    15 }
    16 
    17 void ssort()
    18 {
    19     for(R i = 1; i <= n; i ++) ++ d[p2[i]];
    20     for(R i = 1; i <= m; i ++) d[i] += d[i - 1];
    21     for(R i = 1; i <= n; i ++) b[d[p2[i]] --] = i;//为i分配d[p2[i]]的排名
    22     for(R i = 0; i <= m; i ++) d[i] = 0;
    23     
    24     for(R i = 1; i <= n; i ++) ++ d[p1[i]];
    25     for(R i = 1; i <= m; i ++) d[i] += d[i - 1];
    26     for(R i = n; i; --  i) sa[d[p1[b[i]]] --] = b[i];//为b[i]分配d[p1[b[i]]]的排名(按序分配)
    27     for(R i = 0; i <= m; i ++) d[i] = 0;
    28 }
    29 
    30 void sa_sort()
    31 {
    32     for(R k = 1; k <= n; k <<= 1)
    33     {
    34         for(R i = 1; i <= n; i ++) p1[i] = rk[i], p2[i] = rk[i + k];
    35         ssort();
    36         int tmp = 1;
    37         rk[sa[1]] = 1;
    38         for(R i = 2; i <= n; i ++)
    39             rk[sa[i]] = (p1[sa[i - 1]] == p1[sa[i]] && p2[sa[i - 1]] == p2[sa[i]]) ? tmp : ++ tmp;
    40         if(tmp >= n) break;
    41         m = tmp;
    42     }
    43 }
    44 
    45 void work()
    46 {
    47     for(R i = 1; i <= n; i ++)
    48     {
    49         if(sa[i] > len) continue;
    50         printf("%c", s[sa[i] + len - 1]);
    51     }
    52     printf("
    ");
    53 }
    54 
    55 int main()
    56 {
    57 //    freopen("in.in", "r", stdin);
    58     pre();
    59     sa_sort();
    60     work();    
    61 //    fclose(stdin);
    62     return 0;
    63 }
    View Code

      

  • 相关阅读:
    Windows下sqlmap的使用_01
    连接查询中on and和on where的区别
    java中的BigDecimal和String的相互转换
    Linux使用rarcrack暴力破解RAR,ZIP,7Z压缩包
    oralce 日期 date 相关操作
    scp
    linux网络配置
    Linux防火墙--iptables--白名单配置
    ORACLE 查询所有表、外键、主键等信息
    openssl版本升级
  • 原文地址:https://www.cnblogs.com/ww3113306/p/10067289.html
Copyright © 2020-2023  润新知