【BZOJ2882】工艺 [SAM]

工艺

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

  小敏和小燕是一对好朋友。
  他们正在玩一种神奇的游戏,叫Minecraft。
  他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
  他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
  两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。

Input

  第一行两个整数n,代表方块的数目。
  第二行n个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。

Output

  一行n个整数,代表最美观工艺品从左到右瑕疵度的值。

Sample Input

  10
  10 9 8 7 6 5 4 3 2 1

Sample Output

  1 10 9 8 7 6 5 4 3 2

HINT

   对于100%的数据,n<=300000

Main idea

  给定一个环,问从哪一位往后走开始得到的串字典序最小。

Solution

  我们先把串复制一遍,然后建立一个SAM,然后贪心地走最小的即可。由于SAM的种种奇特♂性质,一定可以走完n个,输出即可。由于数字很大,数组不够存,于是我们使用map。

Code

 

 1 #include<iostream>    
 2 #include<string>    
 3 #include<algorithm>    
 4 #include<cstdio>    
 5 #include<cstring>    
 6 #include<cstdlib>    
 7 #include<cmath>
 8 #include<map>
 9 using namespace std;  
10      
11 const int ONE=1200005;
12 const int INF=2147483640;
13  
14 map <int,int> a[ONE];
15  
16 int n,ch[ONE];
17 int len[ONE],fa[ONE];
18  
19 int get()
20 {    
21         int res=1,Q=1;char c;    
22         while( (c=getchar())<48 || c>57 ) 
23         if(c=='-')Q=-1; 
24         res=c-48;     
25         while( (c=getchar())>=48 && c<=57 )    
26         res=res*10+c-48;    
27         return res*Q;    
28 }
29  
30 struct SAM
31 {
32         int last, cnt;
33         SAM() {last = cnt = 1;}
34         void Add(int c)
35         {
36             int x = last, New = last = ++cnt;
37             len[New] = len[x] + 1;
38             while(x && !a[x][c]) a[x][c] = New, x = fa[x];
39             if(!x) {fa[New] = 1; return;}
40              
41             int q = a[x][c];
42             if(len[q] == len[x] + 1) fa[New] = q;
43             else
44             {
45                 int Nq = ++cnt; len[Nq] = len[x] + 1;
46                 a[Nq] = a[q];
47                 fa[Nq] = fa[q];
48                 fa[New] = fa[q] = Nq;
49                 while(a[x][c] == q) a[x][c] = Nq, x = fa[x];
50             }
51         }
52          
53         void Run()
54         {
55             map <int,int>::iterator it;
56             int x = 1;
57             for(int i=1; i<=n; i++)
58             {
59                 it = a[x].begin();
60                 x = it->second;
61                 if(i!=n) printf("%d ", it->first);
62                 else printf("%d", it->first);
63             }
64         }
65 }S;
66  
67 int main()  
68 {
69         n = get();
70         for(int i=1; i<=n; i++) ch[i] = get();
71         for(int i=1; i<=n*2; i++) i<=n ? S.Add(ch[i]):S.Add(ch[i-n]); 
72          
73         S.Run();
74 }
View Code

 

 

 

posted @ 2017-05-17 11:41  BearChild  阅读(215)  评论(0编辑  收藏  举报