zoukankan      html  css  js  c++  java
  • 【NOI2015】品酒大会 SAM

    论没有看完题目的危害,以及预处理不做号的危害。两个小时过去了…………………………………………

    不难。把字符串逆序建后缀自动机,利用fail边得到后缀树。(理解上的,实际上没有在树上跑。)

    由于后缀树上每一个叶子节点所代表的串是原串的后缀。现在逆序之后,就变成了前缀。那

    因为一个节点x的sz数组表示这个节点所代表的所有的串都出现了sz[x]次。而且该串所代表的字符串长度为 dep[fa[x]] + 1 ~ dep[x] 所以理论上考虑一个节点对答案的贡献是是要对 dep[fa[x]+1] ~ dep[x]都加一次的。但是很显然有前缀和的思想,那么就不用了。

    总而言之。后缀自动机的思想就是用一个长串已有的信息,和它的后缀的信息汇总。进而得出全部的信息。

    (特别地,对于任意的 1p,qn1≤p,q≤n,pqp≠q,第 pp 杯酒和第 qq杯酒都是“0相似”的。)不知道是否有人和我一样没看题。而且有些maxl,minl没初始化,WA了好久。心好累。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define rep(i,j,k) for(register int i = j; i <= k; i++)
     5 #define dow(i,j,k) for(register int i = j; i >= k; i--)
     6 #define maxn 302333
     7 #define ll long long
     8 #define inf 0x7fffffff
     9 using namespace std;
    10 
    11 inline int read() {
    12     int s = 0, t = 1; char c = getchar();
    13     while( !isdigit(c) ) { if( c == '-' ) t = -1; c = getchar(); }
    14     while( isdigit(c) ) s = s * 10 + c - 48, c = getchar();
    15     return s * t;  
    16 }
    17 
    18 int u, p, last = 1, tot = 1, v, nv, dep[maxn<<1], fa[maxn<<1], sz[maxn<<1];  
    19 int maxl[maxn<<1][2], minl[maxn<<1][2], son[maxn<<1][26];
    20 inline void extend(int c,int key) {
    21     u = last; last = p = ++tot; dep[p] = dep[u] + 1; sz[p] = 1;
    22     maxl[p][0] = minl[p][0] = key; //cout<<"B "<<p<<" "<<key<<endl;
    23     maxl[p][1] = -2e9; minl[p][1] = 2e9;
    24     while( u && !son[u][c] ) son[u][c] = p, u = fa[u];
    25     if( !u ) fa[p] = 1;
    26     else {
    27         v = son[u][c];
    28         if( dep[v] == dep[u] + 1 ) fa[p] = v;
    29         else {
    30             nv = ++tot; dep[nv] = dep[u] + 1;
    31             fa[nv] = fa[v]; fa[v] = fa[p] = nv;
    32             maxl[tot][0] = maxl[tot][1] = -2e9;
    33             minl[tot][0] = minl[tot][1] = 2e9;
    34             memcpy(son[nv],son[v],sizeof(son[v]));
    35             while( son[u][c] == v ) son[u][c] = nv, u = fa[u];
    36         }
    37     }
    38 }
    39 
    40 int q[maxn<<1], tong[maxn<<1] = {0}, key[maxn];
    41 inline void pre() {
    42     rep(i,1,tot) tong[dep[i]]++;
    43     rep(i,1,tot) tong[i] += tong[i-1];
    44     dow(i,tot,1) q[tong[dep[i]]--] = i;
    45     int x;
    46     dow(i,tot,1) x = q[i], sz[fa[x]] += sz[x];
    47     dep[0] = -1; 
    48 } 
    49 ll cnt[maxn], ans[maxn]; char c[maxn];
    50 inline void updatemax(int x,int v) {
    51 //    cout<<"M "<<x<<" "<<v<<" "<<maxl[x][1]<<" ";
    52     maxl[x][1] = max(maxl[x][1],v);
    53 //    cout<<maxl[x][1]<<endl;
    54     if( maxl[x][1] > maxl[x][0] ) swap(maxl[x][1],maxl[x][0]);
    55 }
    56 inline void updatemin(int x,int v) {
    57 //    cout<<"I "<<x<<" "<<v<<" "<<minl[x][1]<<" ";
    58     minl[x][1] = min(minl[x][1],v);
    59 //    cout<<minl[x][1]<<endl;
    60     if( minl[x][1] < minl[x][0] ) swap(minl[x][1],minl[x][0]);
    61 }
    62 
    63 int main() {
    64     int n = read(); scanf("%s", c+1);
    65     maxl[1][0] = maxl[1][1] = -2e9; minl[1][0] = minl[1][1] = 2e9;
    66     rep(i,1,n) key[i] = read();
    67     dow(i,n,1) extend(c[i]-'a',key[i]);
    68     pre(); int x;
    69     memset(ans,128,sizeof(ans));
    70     memset(cnt,0,sizeof(cnt));
    71     dow(i,tot,1) {
    72         x = q[i];
    73         if( sz[x] > 1 ) {
    74             cnt[dep[x]] += 1ll * (sz[x] - 1) * sz[x] / 2;
    75             if( dep[fa[x]] >= 0 ) cnt[dep[fa[x]]] -= 1ll * (sz[x] - 1) * sz[x] / 2;
    76             ans[dep[x]] = max(ans[dep[x]],max(1ll*maxl[x][0]*maxl[x][1],1ll*minl[x][0]*minl[x][1]));
    77         } 
    78         updatemax(fa[x],maxl[x][0]);
    79         updatemax(fa[x],maxl[x][1]);
    80         updatemin(fa[x],minl[x][0]);
    81         updatemin(fa[x],minl[x][1]);
    82     } 
    83     dow(i,n-1,0) cnt[i] += cnt[i+1]; 
    84     dow(i,n-1,0) ans[i] = max(ans[i],ans[i+1]); 
    85     rep(i,0,n-1) if( !cnt[i] ) ans[i] = 0;
    86     rep(i,0,n-1) printf("%lld %lld
    ", cnt[i],ans[i]); 
    87  //   x = read();
    88     return 0;
    89 }
  • 相关阅读:
    值得学习的C语言开源项目
    iOS – 使用UINib加载xib文件实现UITableViewCell
    iOS – 滚动视图(UIScrollView)详解
    oracle的体系结构之网络配置和登录验证(四)
    oracle的体系结构之存储结构(三)
    oracle的体系结构之权限管理和用户schema(二)
    oracle的体系结构之基本概念(一)
    C++ 闭包(closure)
    C++ Lambda 表达式
    C++ 类成员的构造和析构顺序
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5485529.html
Copyright © 2011-2022 走看看