CSU – 1632 Repeated Substrings 后缀数组、distinct substring

ProLightsfx 2017-2-22 147 2/22

Repeated Substrings 后缀数组、distinct substring

 Source

CSU - 1632

My Solution

题意:给出一个字符串,找出出现2次及以上的子串的种数。

后缀数组

跑出sa数组和height数组,然后从i = 2 ~ n遍历,每次 ans += max(0, heigt[i] - lastheight);

这里减掉的是已经计算过的子串种数,可参考比此题稍难的 HDU - 3948 The Number of Palindromes 后缀数组+ST表、distinct substring

复杂度 O(nlogn)
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 8;
int sa[maxn], height[maxn];
int _rank[maxn], t1[maxn], t2[maxn], c[maxn];
string s;
inline void get_sa(const int &n, int m)
{
    int i, k, *x = t1, *y = t2, p, j;
    for(i = 0; i < m; i++) c[i] = 0;
    for(i = 0; i < n; i++) ++ c[x[i] = s[i]];
    for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[-- c[x[i]]] = i;
    for(k = 1; k <= n; k <<= 1){
        p = 0;
        for(i = n - k; i < n; i++) y[p ++] = i;
        for(i = 0; i < n; i++) if(sa[i] >= k) y[p ++] = sa[i] - k;
        for(i = 0; i < m; i++) c[i] = 0;
        for(i = 0; i < n; i++) ++ c[x[y[i]]];
        for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y), p = 1, x[sa[0]] = 0;
        for(i = 1; i < n; i++) x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]) ? p - 1 : p ++; if(p >= n) break;
        m = p;
    }
    k = 0;
    for(i = 0; i < n; i++) _rank[sa[i]] = i;
    for(i = 0; i < n; i++){
        if(k) --k; if(!_rank[i]) continue;
        j = sa[_rank[i] - 1];
        while(s[i + k] == s[j + k]) k++;
        height[_rank[i]] = k;
    }
}

inline void print(const int &n)
{
    for(int i = 1; i <= n; i++){ //sa and height is 1~n based
        //cout << i << " : " << _rank[sa[i]] << " " << sa[i] << endl;
        for(int j = sa[i]; j < n; j++){ //the context is 0~n-1 based
            cout << s[j];
        }
        cout << endl;
    }
    cout << endl; } int main() { #ifdef LOCAL freopen("10.in", "r", stdin); //freopen("10.out", "w", stdout); #endif // LOCAL ios::sync_with_stdio(false); cin.tie(0); int T, n, sz, i, o, ans; cin >> T;
    while(T--){
        cin >> s;
        sz = s.size();
        n = sz;
        get_sa(n+1, 256);
        //print(n);
        ans = o = 0;
        for(i = 2; i <= n; i++){
            ans += max(0, height[i] - o); o =height[i];
            //last line can be changed to "ans += max(0, height[i] - height[i-1]);"
        }
        cout << ans << "n";
    }
    return 0;
}


非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

https://www.prolightsfxjh.com/

Thank you!

                                                                                                                                             ------from ProLightsfx

- THE END -

ProLightsfx

11月15日18:45

最后修改:2024年11月15日
0

非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

共有 0 条评论