HDU3518 Boring counting

Suffix array

Requires more than twice the substring statistics do not overlap occurs, in fact, prefixes and suffixes of more than two non-overlapping statistics appear difficult to think of an array of height.

Adjacent suffix only contain and included relationship, or is not in the same block, the prefix repeated affirmation of height in this piece, so we count the minimum and maximum continuous block sa subtracted to determine whether the condition can be.

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define __fastIn ios::sync_with_stdio(false), cin.tie(0)
#define pb push_back
using namespace std;
using LL = long long;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int ret = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        ret = (ret << 3) + (ret << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -ret : ret;
}
template <typename A>
inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
const int N = 2000;
string s;
LL ans;

namespace SuffixArray{

    string s;
    int sa[N], t[N], t2[N], c[N], rank[N], height[N];

    void build(int m, int n){
        int *x = t, *y = t2;
        for(int i = 0; i < m; i ++) c[i] = 0;
        for(int i = 0; i < n; i ++) c[x[i] = s[i]] ++;
        for(int i = 0; i < m; i ++) c[i] += c[i - 1];
        for(int i = n - 1; i >= 0; i --) sa[--c[x[i]]] = i;
        for(int k = 1; k <= n; k <<= 1){
            int p = 0;
            for(int i = n - k; i < n; i ++) y[p++] = i;
            for(int i = 0; i < n; i ++){
                if(sa[i] >= k) y[p++] = sa[i] - k;
            }
            for(int i = 0; i < m; i ++) c[i] = 0;
            for(int i = 0; i < n; i ++) c[x[y[i]]] ++;
            for(int i = 0; i < m; i ++) c[i] += c[i - 1];
            for(int i = n - 1; i >= 0; i --) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1, x[sa[0]] = 0;
            for(int i = 1; i < n; i ++){
                x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && sa[i - 1] + k < n &&
                        sa[i] + k < n && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p ++;
            }
            if(p >= n) break;
            m = p;
        }

        int k = 0;
        for(int i = 0; i < n; i ++) rank[sa[i]] = i;
        for(int i = 0; i < n; i ++){
            if(!rank[i]) continue;
            if(k) k --;
            int j = sa[rank[i] - 1];
            while(s[i + k] == s[j + k]) k ++;
            height[rank[i]] = k;
        }
    }
}

using SuffixArray::build;
using SuffixArray::sa;
using SuffixArray::height;

bool solve(int k){
    bool good = false;
    int l = INF, r = 0;
    for(int i = 1; i < s.size(); i ++){
        if(height[i] >= k){
            l = min(l, min(sa[i], sa[i - 1]));
            r = max(r, max(sa[i], sa[i - 1]));
        }
        else{
            if(r - l >= k) ans ++, good = true;
            l = INF, r = 0;
        }
    }
    if(r - l >= k) ans ++, good = true;
    return good;
}

int main(){

    __fastIn;

    while(cin >> s && s != "#"){
        SuffixArray::s = s;
        build(128, (int)s.size());
        ans = 0;
        for(int i = 1; i <= (s.size() + 1) / 2; i ++){
            if(!solve(i)) break;
        }
        cout << ans << endl;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/onionQAQ/p/11411380.html