「bjwc2010」外星联络

Source and Judge

BJWC2010
bzoj2251
luogu4341

Record

1h

Analysis

请先思考后再展开

水题
后缀排好序,然后每个后缀访问其前缀,向后面暴力询问hei
总势能显然是n方的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109


#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
#include<set>
#include<queue>
#include<deque>
#include<stack>
#include<bitset>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
#ifdef DEBUG
const int LOCAL=1;
#else
const int LOCAL=0;
#endif

namespace mine
{
typedef long long ll;
const int INF=0x3f3f3f3f;
int ()
{
int ans=0,f=1;char c=getchar();
while(c<'0' or c>'9') {if(c=='-') f=-1;;c=getchar();}
while(c>='0' and c<='9') ans=ans*10+c-'0',c=getchar();
return ans*f;
}

const int MAX_N=3100;
char str[MAX_N];int len;
struct Sa
{
int sa[MAX_N],tmp[MAX_N];
int rk[MAX_N*2],rk2[MAX_N*2];
int ct[MAX_N];
bool diff(int a,int b,int ln) {return rk2[a]!=rk2[b] or rk2[a+ln]!=rk2[b+ln];}
void build()
{
memset(ct,0,sizeof ct);
for(int i=1;i<=len;i++) ct[rk[i]=str[i]]++;
for(int i=1;i<MAX_N;i++) ct[i]+=ct[i-1];
for(int i=len;i>=1;i--) sa[ct[rk[i]]--]=i;

int ln=1;
while(ln<len)
{
int cnt=0;for(int i=len-ln+1;i<=len;i++) tmp[++cnt]=i;
for(int i=1;i<=len;i++) if(sa[i]-ln>=1) tmp[++cnt]=sa[i]-ln;

memset(ct,0,sizeof ct);
for(int i=1;i<=len;i++) ct[rk[tmp[i]]]++;
for(int i=1;i<MAX_N;i++) ct[i]+=ct[i-1];
for(int i=len;i>=1;i--) sa[ct[rk[tmp[i]]]--]=tmp[i];

cnt=0;memcpy(rk2,rk,sizeof rk);sa[0]=0;
for(int i=1;i<=len;i++)
{
if(diff(sa[i-1],sa[i],ln)) cnt++;
rk[sa[i]]=cnt;
}

ln*=2;
}
}
int hei[MAX_N];
void geth()
{
int lst=0;
for(int i=1;i<=len;i++)
{
if(rk[i]==1) {hei[1]=0;continue;}
if(lst) lst--;
while(max(sa[rk[i]-1],i)+lst<=len and str[sa[rk[i]-1]+lst]==str[i+lst]) lst++;
hei[rk[i]]=lst;
}
}
}sa;
int bom[MAX_N];
void main()
{
scanf("%d%s",&len,str+1);
sa.build();
sa.geth();
//for(int i=1;i<=len;i++) printf("%d ",sa.hei[i]);
//puts("");

for(int i=1;i<=len;i++)
{
int pos=sa.sa[i];
for(int t=bom[i]+1;pos+t-1<=len;t++)
{
int nxt=i;
while(nxt+1<=len and sa.hei[nxt+1]>=t) bom[++nxt]=t;
if(nxt-i+1>1) printf("%dn",nxt-i+1);
}
}
}
};
int main()
{
srand(time(0));
mine::main();
}