• [NOI2015]品酒大会


    建出SAM和后缀树

    两个子串的最长lcp就是他们的lca

    因此我们只需求出最长的个数然后用前缀和就能算出总个数,最大值也是同样的方法, 当然要逆序建SAM才能保证他们的第一位相同。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define LL long long
      6 
      7 using namespace std;
      8 
      9 inline LL read()
     10 {
     11     LL x = 0, w = 1; char ch = 0;
     12     while(ch < '0' || ch > '9') {
     13         if(ch == '-') {
     14             w = -1;
     15         }
     16         ch = getchar();
     17     }
     18     while(ch >= '0' && ch <= '9') {
     19         x = x * 10 + ch - '0';
     20         ch = getchar();
     21     }
     22     return x * w;
     23 }
     24 
     25 const int MAXN = 1e6 + 10;
     26 
     27 int head[MAXN];
     28 char s[MAXN];
     29 LL d[MAXN];
     30 LL ans[MAXN], num[MAXN];
     31 LL fi, se;
     32 int flag[MAXN];
     33 LL size[MAXN];
     34 LL maxn[MAXN], minn[MAXN];
     35 int len;
     36 int lst = 1, tot = 1;
     37 
     38 struct SAM {
     39     int c[27];
     40     int fa, len;
     41 } t[MAXN];
     42 
     43 void extend(int x, int d)
     44 {
     45     int last = lst, np = ++tot;
     46     t[np].len = t[last].len + 1;
     47     size[np] = 1;
     48     lst = np;
     49     maxn[np] = minn[np] = d;
     50     while(last && !t[last].c[x]) {
     51         t[last].c[x] = np;
     52         last = t[last].fa; 
     53     }
     54     if(!last) {
     55         t[np].fa = 1;
     56     } else {
     57         int q = t[last].c[x];
     58         if(t[q].len == t[last].len + 1) {
     59             t[np].fa = q;
     60         } else {
     61             int nq = ++tot;
     62             flag[nq] = 1;
     63             maxn[nq] = -2e18, minn[nq] = 2e18;
     64             t[nq] = t[q];
     65             t[nq].len = t[last].len + 1;
     66             t[np].fa = t[q].fa = nq;
     67             while(t[last].c[x] == q) {
     68                 t[last].c[x] = nq;
     69                 last = t[last].fa;
     70             }
     71         }
     72     }
     73 }
     74 
     75 int cnt = 0;
     76 
     77 struct edge {
     78     int v, next;
     79 } g[MAXN];
     80 
     81 void addedge(int u, int v)
     82 {
     83     g[++cnt].v = v;
     84     g[cnt].next = head[u];
     85     head[u] = cnt;    
     86 }
     87 
     88 bool ok(int x)
     89 {
     90     return maxn[x] != -2e18 && minn[x] != 2e18;
     91 }
     92 
     93 void DFS(int x)
     94 {    
     95     for(int j = head[x]; j; j = g[j].next) {
     96         int to = g[j].v;
     97         DFS(to);
     98         num[t[x].len] += size[x] * size[to];
     99         size[x] += size[to];
    100         if(ok(x) && ok(to)) {
    101             ans[t[x].len] = max(ans[t[x].len], max(maxn[x] * maxn[to], minn[x] * minn[to]));
    102         }
    103         maxn[x] = max(maxn[x], maxn[to]);
    104         minn[x] = min(minn[x], minn[to]);
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     //freopen("drink.out", "w", stdout);
    111     len = read();
    112     scanf("%s", s + 1);
    113     fi = -2e18, se = 2e18;
    114     maxn[1] = -2e18, minn[1] = 2e18;
    115     for(int i = 1; i <= len; i++) {
    116         d[i] = read();
    117         if(fi != -2e18)
    118         ans[0] = max(fi * d[i], ans[0]);
    119         if(se != 2e18)
    120         ans[0] = max(se * d[i], ans[0]);
    121         fi = max(fi, d[i]), se = min(se, d[i]);
    122     }
    123     for(int i = 0; i <= len; i++) {
    124         ans[i] = -2e18;
    125     }
    126     for(int i = len; i >= 1; i--) {
    127         extend(s[i] - 'a', d[i]);
    128     }
    129     for(int i = 2; i <= tot; i++) {
    130         addedge(t[i].fa, i);
    131     }
    132     DFS(1);
    133     for(int i = len - 1; i >= 0; i--) {
    134         num[i] += num[i + 1];
    135         ans[i] = max(ans[i], ans[i + 1]);
    136     }
    137     for(int i = 0; i < len; i++) {
    138         if(num[i] == 0) {
    139             printf("0 0
    ");
    140         } else {
    141             printf("%lld %lld
    ", num[i], ans[i]);
    142         }
    143     }
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    UVA11082 矩阵展开,最大流
    UVA11082 矩阵展开,最大流
    hdu5855二分+最大流
    hdu5855二分+最大流
    高斯消元 hdu5833,hdu3364,hihocoder1195
    高斯消元 hdu5833,hdu3364,hihocoder1195
    傅里叶分析之掐死教程
    傅里叶分析之掐死教程
    php字符串大小写转换
    php strip_tags() 函数去除 HTML、XML 以及 PHP 的标签。
  • 原文地址:https://www.cnblogs.com/wuenze/p/9255936.html
Copyright © 2020-2023  润新知