[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("\n");
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

 

  

posted @ 2018-12-04 21:27  ww3113306  阅读(158)  评论(0编辑  收藏  举报
知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。