zoukankan      html  css  js  c++  java
  • AHOI2013 差异

    传送门

    我一开始的想法是直接去求后面的(lcp(T_i,T_j)),但是我不会……

    有一条性质:两个后缀的(lcp)就是他们在(parent)树上的(LCA),而且出题人给这个式子其实是有目的的……我们把式子拆开,对于每一条边,我们赋一个权值为(l[i] - l[fa[i]]),这样的话我们只要求出所有边对于答案的贡献就行了……

    对于一条边的话,肯定会被经过(size[i] * (n - size[i]))次的。

    那么我们建出SAM,之后在上面拓扑排序跑一遍更新答案即可。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(register int i = a;i <= n;i++)
    #define per(i,n,a) for(register int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    const int N = 10000005;
    
    int read()
    {
        int ans = 0,op = 1;char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
        while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
        return ans * op;
    }
    
    char s[M];
    int n,a[M<<1],c[M<<1];
    ll ans;
    
    struct SaffixAutomaton
    {
        int last,cnt,ch[M<<2][26],fa[M<<1],l[M<<1],size[M<<1];
        void extend(int c)
        {
            int p = last,np = ++cnt;
            last = cnt,l[np] = l[p] + 1,size[np] = 1;
            while(p && !ch[p][c]) ch[p][c] = np,p = fa[p];
            if(!p) {fa[np] = 1;return;}
            int q = ch[p][c];
            if(l[q] == l[p] + 1) fa[np] = q;
            else
            {
                int nq = ++cnt;
                l[nq] = l[p] + 1,memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq] = fa[q],fa[q] = fa[np] = nq;
                while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
            }
        }
        void calc()
        {
            rep(i,1,cnt) c[l[i]]++;
            rep(i,1,cnt) c[i] += c[i-1];
            rep(i,1,cnt) a[c[l[i]]--] = i;
            per(i,cnt,1) 
            {
                int p = a[i];
                size[fa[p]] += size[p];
                ans += 1ll * (l[p] - l[fa[p]]) * (size[p]) * (n - size[p]);
            }
            
        }
    }SAM;
    
    int main()
    {
        scanf("%s",s+1),n = strlen(s+1);
        SAM.last = SAM.cnt = 1;
        rep(i,1,n) SAM.extend(s[i] - 'a');
        SAM.calc(),printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    笔记:多线程访问ConcurrentHashMap对key加锁
    根据第三列去重
    Correct the classpath of your application so that it contains a single, compatible version of org.apache.log4j.ConsoleAppender
    python 中将源配置为阿里
    criteria两个 判断
    git flow
    sqlmap用法详解
    MongoDB 入门
    MongoDB 手册
    OWASP TOP 10简单介绍
  • 原文地址:https://www.cnblogs.com/captain1/p/10261081.html
Copyright © 2011-2022 走看看