首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

CSU 1656 Paper of FlyBrother:後綴數組求不同子串個數

     編輯:關於C++

問題轉化

字符串長度 n ≤ 1e5。不同子串總數 = 所有後綴長度之和 − 相鄰後綴 LCP 之和。
即 ans = n(n+1)/2 - ∑_{i=1}^{n-1} height[i],其中 height[i] = SA[i] 與 SA[i-1] 的最長公共前綴。

後綴數組構建:倍增算法 O(n log n)


void buildSA(string s) {
    int n = s.size(); s += '$'; // 哨兵
    vector sa(n+1), rnk(n+1), tmp(n+1);
    for (int i=0;i<=n;++i) { sa[i]=i; rnk[i]=s[i]; }
    for (int k=1;k<=n;k<<=1) {
        auto cmp = [&](int i, int j) {
            if (rnk[i]!=rnk[j]) return rnk[i]

Height 數組計算:Kasai 算法 O(n)


void buildHeight(string s, vector& sa, vector& height) {
    int n = s.size();
    vector rnk(n+1);
    for (int i=1;i<=n;++i) rnk[sa[i]] = i;
    int h = 0;
    for (int i=0;i 1) {
            int j = sa[rnk[i]-1];
            while (i+h

完整求解


long long countDistinctSubstrings(string s) {
    int n = s.size();
    vector sa, height;
    buildSA(s); buildHeight(s, sa, height);
    long long total = 1LL * n * (n + 1) / 2;
    for (int i=2;i<=n;++i) total -= height[i];
    return total;
}

複雜度

構建 SA O(n log n),Height O(n),總 O(n log n),n=1e5 時 < 0.5s。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved