zoukankan      html  css  js  c++  java
  • BZOJ4650 : [NOI2016]优秀的拆分

    题面

    传送门

    Sol

    求个以(i)为结尾的(AA)串的个数和以(i)为开头的(AA)串的个数
    乘法原理即可,暴力求有95分
    而你会发现,枚举l,经过(i)(i+l)的只要算出它左右各能扩展到哪里,然后这个区间内的都要(+1)
    差分一下+后缀数组

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(1e5 + 5);
    
    IL ll Input(){
        RG ll x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, pre[_], suf[_], lg[_];
    ll ans = 0;
    char s[_];
    struct SA{
        int a[_], t[_], tmp[_], rk[_], sa[_], height[_], st[20][_];
    
    	IL void Init(){
    		Fill(a, 0);
    	}
    	
        IL bool Cmp(RG int x, RG int y, RG int z){
            return tmp[x] == tmp[y] && x + z <= n && y + z <= n && tmp[x + z] == tmp[y + z];
        }
    
        IL void Suffix_Sort(){
            RG int m = 26;
            for(RG int i = 0; i <= m; ++i) t[i] = 0;
            for(RG int i = 1; i <= n; ++i) ++t[rk[i] = a[i]];
            for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
            for(RG int i = n; i; --i) sa[t[rk[i]]--] = i;
            for(RG int k = 1; k <= n; k <<= 1){
                RG int l = 0;
                for(RG int i = n - k + 1; i <= n; ++i) tmp[++l] = i;
                for(RG int i = 1; i <= n; ++i) if(sa[i] > k) tmp[++l] = sa[i] - k;
                for(RG int i = 0; i <= m; ++i) t[i] = 0;
                for(RG int i = 1; i <= n; ++i) ++t[rk[tmp[i]]];
                for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
                for(RG int i = n; i; --i) sa[t[rk[tmp[i]]]--] = tmp[i];
                swap(rk, tmp); rk[sa[1]] = l = 1;
                for(RG int i = 2; i <= n; ++i) rk[sa[i]] = Cmp(sa[i - 1], sa[i], k) ? l : ++l;
                if(l >= n) break;
                m = l;
            }
            for(RG int i = 1, h = 0; i <= n; ++i){
                if(h) --h;
                while(a[i + h] == a[sa[rk[i] - 1] + h]) ++h;
                height[rk[i]] = h;
            }
        }
    
        IL void ST_Prepare(){
            for(RG int i = 1; i <= n; ++i) st[0][i] = height[i];
            for(RG int i = 1; i <= lg[n]; ++i)
                for(RG int j = 1; j + (1 << i) - 1 <= n; ++j)
                    st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
        }
    
        IL int LCP(RG int x, RG int y){
            x = rk[x]; y = rk[y];
            if(x > y) swap(x, y);
            RG int len = lg[y - x];
            return min(st[len][x + 1], st[len][y - (1 << len) + 1]);
        }
    } A, B;
    
    int main(RG int argc, RG char* argv[]){
        for(RG int i = 2; i <= 30000; ++i) lg[i] = lg[i >> 1] + 1;
        for(RG int T = Input(); T; --T){
    		A.Init(); B.Init();
            scanf(" %s", s + 1);
            n = strlen(s + 1); ans = 0;
            for(RG int i = 1; i <= n; ++i){
                B.a[n - i + 1] = A.a[i] = s[i] - 'a' + 1;
                suf[i] = pre[i] = 0;
            }
            A.Suffix_Sort(); A.ST_Prepare();
            B.Suffix_Sort(); B.ST_Prepare();
            for(RG int l = 1; l + l <= n; ++l)
                for(RG int i = l; i + l <= n; i += l){
                    RG int r = i + l, x = min(A.LCP(i, r), l), y = min(B.LCP(n - i + 1, n - r + 1), l), len = x + y - l;
                    if(x + y > l){
                        suf[i - y + 1]++; suf[i - y + 1 + len]--;
                        pre[r + x - len]++; pre[r + x]--;
                    }
                }
            for(RG int i = 1; i <= n; ++i) pre[i] += pre[i - 1], suf[i] += suf[i - 1];
            for(RG int i = 1; i < n; ++i) ans += 1LL * pre[i] * suf[i + 1];
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    POJ 1300 Open Door
    POJ 2230 Watchcow
    codevs 1028 花店橱窗布置
    codevs 1021 玛丽卡
    codevs 1519 过路费
    codevs 3287 货车运输
    codevs 3305 水果姐逛水果街二
    codevs 1036 商务旅行
    codevs 4605 LCA
    POJ 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8361580.html
Copyright © 2011-2022 走看看