SPOJ 7258 (后缀自动机)

转载:http://hzwer.com/4492.html

给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个。

搞出后缀自动机

dp处理出每个点往下走能够走出多少个串。
f[i]=sigma(f[ch[i][c])+1
这个可以按Max排序之后倒着推就好了。
询问的时候看一下走下去个数是否<=k,是的话就走下去,然后–k;否则就找下一条边

  1 1
  2 2
  3 3
  4 4
  5 5
  6 6
  7 7
  8 8
  9 9
 10 10
 11 11
 12 12
 13 13
 14 14
 15 15
 16 16
 17 17
 18 18
 19 19
 20 20
 21 21
 22 22
 23 23
 24 24
 25 25
 26 26
 27 27
 28 28
 29 29
 30 30
 31 31
 32 32
 33 33
 34 34
 35 35
 36 36
 37 37
 38 38
 39 39
 40 40
 41 41
 42 42
 43 43
 44 44
 45 45
 46 46
 47 47
 48 48
 49 49
 50 50
 51 51
 52 52
 53 53
 54 54
 55 55
 56 56
 57 57
 58 58
 59 59
 60 60
 61 61
 62 62
 63 63
 64 64
 65 65
 66 66
 67 67
 68 68
 69 69
 70 70
 71 71
 72 72
 73 73
 74 74
 75 75
 76 76
 77 77
 78 78
 79 79
 80 #include<iostream>
 81 #include<cstdio>
 82 #include<cstring>
 83 #include<cstdlib>
 84 #include<algorithm>
 85 #include<cmath>
 86 #define N 180005
 87 #define inf 1000000000
 88 using namespace std;
 89 char ch[N];
 90 int Q,p,q,np,nq;
 91 int cnt=1,last=1,n;
 92 int fa[N],to[N][26],l[N],s[N];
 93 int f[N],v[N];
 94 void extend(int c)
 95 {
 96     p=last;np=last=++cnt;l[np]=++n;
 97     for(;p&&!to[p][c];p=fa[p])to[p][c]=np;
 98     if(!p)fa[np]=1;
 99     else 
100     {
101         int q=to[p][c];
102         if(l[p]+1==l[q])fa[np]=q;
103         else 
104         {
105             nq=++cnt;l[nq]=l[p]+1;
106             memcpy(to[nq],to[q],sizeof(to[q]));
107             fa[nq]=fa[q];
108             fa[q]=fa[np]=nq;
109             for(;to[p][c]==q;p=fa[p])to[p][c]=nq;
110         }
111     }
112 }
113 void build()
114 {
115     scanf("%s",ch);
116     for(char *c=ch;*c;c++)extend(*c-'a');    
117 }
118 void pre()
119 {
120     for(int i=1;i<=cnt;i++)v[l[i]]++;
121     for(int i=1;i<=n;i++)v[i]+=v[i-1];
122     for(int i=1;i<=cnt;i++)s[v[l[i]]--]=i;
123     for(int i=cnt;i;i--)
124     {
125         f[s[i]]=1;
126         for(int j=0;j<26;j++)
127             f[s[i]]+=f[to[s[i]][j]];
128     }
129 }
130 void query()
131 {
132     p=1;int x;
133     scanf("%d",&x);
134     while(x)
135     {
136         for(int i=0;i<26;i++)
137             if(to[p][i])
138             {
139                 if(f[to[p][i]]>=x)
140                 {
141                     putchar('a'+i);
142                     p=to[p][i];
143                     --x;break;
144                 }
145                 else x-=f[to[p][i]];
146             }
147     }
148     printf("\n");
149 }
150 int main()
151 {
152     build();
153     pre();
154     scanf("%d",&Q);
155     while(Q--)
156         query();
157     return 0;
158 }

 

posted @ 2017-10-19 23:19  抓不住Jerry的Tom  阅读(418)  评论(0编辑  收藏  举报