zoukankan      html  css  js  c++  java
  • [AHOI 2013] 差异

    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=3238

    [算法]

             首先 , LCP(Ti , Tj) = min{ height[rank[Ti] + 1] , height[rank[Ti] + 2] , ... , height[rank[Tj]] }

             显然 , 我们只要计算后缀两两之间的LCP之和即可

             对于一个右端点R , 随着L的减小 , min{height[L] , height[L + 1] .. , height[R]}的值单调递减 , 维护一个单调递增的单调栈即可

             时间复杂度 : O(NlogN)

    [代码]

             

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 500010
    typedef long long ll;
    typedef long double ld;
    const int inf = 1e9;
    
    int n;
    int height[MAXN] , cnt[MAXN] , rk[MAXN] , x[MAXN] , y[MAXN] , sa[MAXN];
    char s[MAXN];
    
    inline ll F(int x)
    {
        return 1ll * x * (x + 1) / 2;
    }
    inline void build_sa()
    {
        memset(cnt , 0 , sizeof(cnt));
        for (int i = 1; i <= n; i++) ++cnt[(int)s[i]];
        for (int i = 1; i <= 256; i++) cnt[i] += cnt[i - 1];
        for (int i = n; i >= 1; i--) sa[cnt[(int)s[i]]--] = i;
        rk[sa[1]] = 1;
        for (int i = 2; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]);
        for (int k = 1; rk[sa[n]] != n; k <<= 1)
        {
            for (int i = 1; i <= n; i++)
                x[i] = rk[i] , y[i] = (i + k <= n) ? rk[i + k] : 0;
            memset(cnt , 0 , sizeof(cnt));
            for (int i = 1; i <= n; i++) ++cnt[y[i]];
            for (int i = 1; i <= n; i++) cnt[i] += cnt[i - 1];
            for (int i = n; i >= 1; i--) rk[cnt[y[i]]--] = i;
            memset(cnt , 0 , sizeof(cnt));
            for (int i = 1; i <= n; i++) ++cnt[x[i]];
            for (int i = 1; i <= n; i++) cnt[i] += cnt[i - 1];
            for (int i = n; i >= 1; i--) sa[cnt[x[rk[i]]]--] = rk[i];
            rk[sa[1]] = 1;
            for (int i = 1; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]] || y[sa[i]] != y[sa[i - 1]]); 
        }
    }
    inline void get_height()
    {
        int k = 0;
        for (int i = 1; i <= n; i++)
        {
            if (k) --k;
            int j = sa[rk[i] - 1];
            while (s[i + k] == s[j + k]) ++k;
            height[rk[i]] = k;
        }    
    }
    inline ll calc_ans()
    {
        int top = 0;
        ll ret = 0;
        static pair<ll , ll> s[MAXN];
        for (int i = 1; i <= n; i++) ret += 1ll * (i - 1) * (n - i + 1) + F(n) - F(n - i + 1);
        s[top = 1] = make_pair(0 , 0);
        ll now = 0;
        for (int i = 1; i <= n; i++)
        {
            int cnt = 1; 
            while (top > 0 && height[i] <= height[s[top].first]) 
            {
                cnt += s[top].second;
                now -= 1ll * height[s[top].first] * s[top].second;
                --top;
            }
            s[++top] = make_pair(i , cnt);
            now += 1ll * height[i] * cnt;
            ret -= 2ll * now;
        }
        return ret;
    }
    
    int main()
    {
        
        scanf("%s" , s + 1);
        n = strlen(s + 1);
        build_sa();
        get_height();
        printf("%lld
    " , calc_ans());
        
        return 0;
    }
  • 相关阅读:
    composer npm bower 版本依赖符号说明
    FastAdmin 速极后台框架从 v1.0 到 v1.2 的数据库升级
    FastAdmin 也可以出书了
    FastAdmin 开发时用到的 Git 命令 (2020-09-26)
    FastAdmin用什么弹窗组件
    笔记:Linux 文件权限
    笔记:使用源代码在 Centos 7 安装 Git 2
    php gd 生成表格 图片
    easyui datagrid 清空
    mysql 去重
  • 原文地址:https://www.cnblogs.com/evenbao/p/10046843.html
Copyright © 2011-2022 走看看