BZOJ 4199: [Noi2015]品酒大会 后缀自动机_逆序更新
细节........
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 1000006
#define inf -0x3f3f3f3f3f3f3f3fll
#define ll long long
using namespace std;
int n,is[maxn],appear[maxn];
long long val[maxn],ans1[maxn],ans2[maxn],maxv[maxn],minv[maxn];
char str[maxn];
// struct Graph{
// int head[maxn],to[maxn],nex[maxn],edges;
// void addedge(int u,int v) { nex[++edges] = head[u],head[u] = edges,to[edges] = v; }
// }G;
struct SAM{
int f[maxn],cnt[maxn],ch[maxn][30],len[maxn],tot,last;
int C[maxn],rk[maxn];
void init() {
tot = last = 1;
for(int i = 0;i < maxn; ++i) ans2[i] = inf;
}
void ins(int c,int cur){
int np = ++tot,p = last; len[np] = len[last] + 1, last = tot;
while(p && !ch[p][c]) ch[p][c] = np,p = f[p];
if(!p) f[np] = 1;
else{
int q = ch[p][c];
if(len[q] == len[p] + 1) f[np] = q;
else {
int nq = ++tot;
len[nq] = len[p] + 1;
is[nq] = 1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
f[nq] = f[q],f[q] = f[np] = nq;
while(p && ch[p][c] == q) ch[p][c] = nq,p = f[p];
}
}
++cnt[last];
maxv[last] = val[cur];
minv[last] = val[cur];
}
void build(){
for(int i = 1;i <= tot; ++i) ++C[len[i]];
for(int i = 1;i <= tot; ++i) C[i] += C[i - 1];
for(int i = 1;i <= tot; ++i) rk[C[len[i]]--] = i;
for(int i = tot;i >= 1; --i) {
int p = rk[i];
ans1[len[f[p]]] += (long long)cnt[f[p]] * cnt[p];
cnt[f[p]] += cnt[p];
if(is[f[p]] && !appear[f[p]])
{
appear[f[p]] = 1;
minv[f[p]] = minv[p];
maxv[f[p]] = maxv[p];
continue;
}
ans2[len[f[p]]] = max(ans2[len[f[p]]],maxv[p]*maxv[f[p]]);
ans2[len[f[p]]] = max(ans2[len[f[p]]],minv[p]*minv[f[p]]);
maxv[f[p]] = max(maxv[f[p]],maxv[p]);
minv[f[p]] = min(minv[f[p]],minv[p]);
}
}
}sam;
int main(){
// setIO("input");
scanf("%d",&n),scanf("%s",str),sam.init();
for(int i = 0;i < n; ++i) scanf("%lld",&val[i]);
for(int i = n - 1;i >= 0; --i) sam.ins(str[i] - 'a',i);
sam.build();
for(int i = n - 1;i >= 0; --i) {
ans1[i] += ans1[i + 1];
ans2[i] = max(ans2[i],ans2[i+1]);
}
for(int i = 0;i < n; ++i) {
if(!ans1[i]) printf("%d %d\n",0,0);
else printf("%lld %lld\n",ans1[i],ans2[i]);
}
return 0;
}