zoukankan      html  css  js  c++  java
  • hihocoder1415 后缀数组三·重复旋律3

    传送门:http://hihocoder.com/problemset/problem/1415

    【题解】

    考虑求出两串合在一起(中间加分隔符)后缀数组,就是要求任意在两个串中的$i, j$,$min{h_k} (i leq k leq j)$的最大值。

    考虑$i, j$一定是满足$|i - j| = 1$且合法的时候最优。

    详情见:hihocoder“解题方法提示”

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    const int mod = 1e9+7;
    
    # define rank RANK
    
    int n, ans;
    char ch[M];
    int sa[M], rank[M], h[M], t[M];
    int tsa[M], cntA[M], cntB[M], A[M], B[M];
    
    inline void    getsa() {
        fill(cntA, cntA + n + 1, 0);
        for (int i=1; i<=n; ++i) cntA[ch[i]] ++;
        for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1];
        for (int i=n; i; --i) sa[cntA[ch[i]] --] = i;
        rank[sa[1]] = 1;
        for (int i=2; i<=n; ++i) {
            rank[sa[i]] = rank[sa[i-1]];
            if(ch[sa[i-1]] != ch[sa[i]]) ++rank[sa[i]];
        }
        for (int len=1; rank[sa[n]] < n; len <<= 1) {
            fill(cntA, cntA + n + 1, 0);
            fill(cntB, cntB + n + 1, 0);
            for (int i=1; i<=n; ++i) {
                cntA[A[i] = rank[i]] ++;
                cntB[B[i] = ((i+len<=n) ? rank[i+len] : 0)] ++;
            }
            for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1], cntB[i] += cntB[i-1];
            for (int i=n; i; --i) tsa[cntB[B[i]] --] = i;
            for (int i=n; i; --i) sa[cntA[A[tsa[i]]] --] = tsa[i];
            rank[sa[1]] = 1;
            for (int i=2; i<=n; ++i) {
                rank[sa[i]] = rank[sa[i-1]];
                if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) ++rank[sa[i]];
            }
        }
    }
            
    inline void getheight() {
        for (int i=1, j=0; i<=n; ++i) {
            if(j) --j;
            while(ch[i+j] == ch[sa[rank[i]-1] + j]) ++j;
            h[rank[i]] = j;
        }
    }
    
    
    int main() {
        scanf("%s", ch+1);
        n = strlen(ch+1);
        int c = n;
        ch[n+1] = '$';
        scanf("%s", ch+n+2);
        n = strlen(ch+1);
    //    printf("%s
    ", ch+1);
        getsa(); getheight();
        for (int i=2; i<=n; ++i) {
            int pre, suf;
            pre = sa[i-1], suf = sa[i];
            if(pre > suf) swap(pre, suf);
            if(pre <= c && suf > c) ans = max(ans, h[i]);
        }
        cout << ans;
        return 0;
    }
    View Code
  • 相关阅读:
    算法导论--第七章、快速排序
    PS操作
    【字符编码】彻底理解字符编码
    HTML网页设计-代码效果记录
    Ubuntu 18.04 nvidia driver 390.48 安装 TensorFlow 1.12.0 和 PyTorch 1.0.0 详细教程
    cmake更新版本简记
    计算机图形学(二)——微表面模型
    计算机图形学(一)——辐照度学概述
    蒙特卡洛积分与重要性采样详解
    for循环提高内存访问效率的做法
  • 原文地址:https://www.cnblogs.com/galaxies/p/hihocoder1415.html
Copyright © 2011-2022 走看看