• [HAOI 2016] 找相同字符


    [题目链接]

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

    [算法]

             首先 , 子串是后缀的前缀

             考虑拼接两个字符串 , 中间用不可见字符隔开 , 求出该字符串的后缀数组

             那么前缀相同的后缀一定排名一定接近

             而我们又知道lcp(i , j) = min{ height[rk[i] + 1] , height[rk[i] + 2] ... , height[rk[j]] }

             维护一个单调递增的后缀数组即可

            时间复杂度 : O(NlogN)(N = |A| + |B|)

    [代码]

             

    #include<bits/stdc++.h>
    using namespace std;
    #define N 400010
    const int ALPHA = 26;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    struct info
    {
        int height;
        int cnta , cntb;
    } ;
    
    int n , m , len;
    int height[N] , rk[N] , sa[N];
    char s[N] , s1[N] , s2[N];
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    inline void build_sa()
    {
        static int x[N] , y[N] , cnt[N];
        memset(cnt , 0 , sizeof(cnt));
        for (int i = 1; i <= len; i++) ++cnt[(int)s[i]];
        for (int i = 1; i <= 256; i++) cnt[i] += cnt[i - 1];
        for (int i = 1; i <= len; i++) sa[cnt[s[i]]--] = i;
        rk[sa[1]] = 1;
        for (int i = 2; i <= len; i++) rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]);
        for (int k = 1; rk[sa[len]] != len; k <<= 1)
        {
            for (int i = 1; i <= len; i++)
                x[i] = rk[i] , y[i] = (i + k <= len) ? rk[i + k] : 0;
            memset(cnt , 0 , sizeof(cnt));
            for (int i = 1; i <= len; i++) ++cnt[y[i]];
            for (int i = 1; i <= len; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) rk[cnt[y[i]]--] = i;
            memset(cnt , 0 , sizeof(cnt));
            for (int i = 1; i <= len; i++) ++cnt[x[i]];
            for (int i = 1; i <= len; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) sa[cnt[x[rk[i]]]--] = rk[i];
            rk[sa[1]] = 1;
            for (int i = 2; i <= len; 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 <= len; i++)
        {
            if (k) --k;
            int j = sa[rk[i] - 1];
            while (s[i + k] == s[j + k]) ++k;
            height[rk[i]] = k;
        }
    }
    inline void merge(info &x , info y)
    {
        x = (info){x.height , x.cnta + y.cnta , x.cntb + y.cntb};
    }
    inline ll calc()
    {
        int top = 0;
        static info s[N];
        ll ret = 0 , va = 0 , vb = 0;
        sa[0] = n + 1;
        for (int i = 1; i <= len; i++)
        {
            info tmp = (info){height[i] , sa[i - 1] < n + 1 , sa[i - 1] > n + 1};
            while (top > 0 && height[i] <= s[top].height)
            {
                va -= 1ll * s[top].height * s[top].cnta;
                vb -= 1ll * s[top].height * s[top].cntb;
                merge(tmp , s[top]);
                --top;
            }
            s[++top] = tmp;
            va += 1ll * s[top].height * s[top].cnta;
            vb += 1ll * s[top].height * s[top].cntb; 
            if (sa[i] < n + 1) ret += vb;
            else ret += va;
        }    
        return ret;
    }
    
    int main()
    {
        
        scanf("%s%s" , s1 + 1 , s2 + 1);
        n = strlen(s1 + 1) ,
        m = strlen(s2 + 1);
        for (int i = 1; i <= n; i++) s[++len] = s1[i];
        s[++len] = '#';
        for (int i = 1; i <= n; i++) s[++len] = s2[i];
        build_sa();
        get_height();
        printf("%lld
    " , calc());
        
        return 0;
    }
  • 相关阅读:
    单链表反转
    C++面试题
    堆排序
    1链表:回文链表(leetcode 234)
    深信服社招linux岗面试记录
    腾讯后台开发社招记录(电话面试)
    小米社招ATE岗位记录
    诺基亚社招C++面试记录
    腾讯后台开发社招面试记录
    makefile笔记
  • 原文地址:https://www.cnblogs.com/evenbao/p/10360329.html
Copyright © 2020-2023  润新知