zoukankan      html  css  js  c++  java
  • bzoj1396

    后缀自动机+线段树

    今天比较颓。。。

    既然只出现一次,那么就是right=1,于是我们预处理出每个点的right,然后看是否等于一,如果是就更新答案。

    更新答案维护两个线段树,如果当前点在延伸[Min,Max]范围内,那么答案就是end-i+1,如果<Min,那么答案就是Min,于是我们维护end+1,再维护Min,end+1最后-i就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e5 + 5, inf = 0x3f3f3f3f;
    int n;
    int f[N << 1], c[N << 1], mp[N << 1], a[N << 1]; 
    char s[N];
    namespace SAM
    {
        struct node {
            int val, par;
            map<int, int> ch;
        } t[N << 1];
        int last = 1, root = 1, sz = 1;
        int nw(int _)
        {
            t[++sz].val = _;
            return sz;
        }
        void extend(int c)
        {
            int p = last, np = nw(t[p].val + 1);
            while(p && !t[p].ch[c]) t[p].ch[c] = np, p = t[p].par;
            if(!p) t[np].par = root;
            else
            {
                int q = t[p].ch[c];
                if(t[q].val == t[p].val + 1) t[np].par = q;
                else
                {
                    int nq = nw(t[p].val + 1);
                    t[nq].ch = t[q].ch;
                    t[nq].par = t[q].par;
                    t[q].par = t[np].par = nq;
                    while(p && t[p].ch[c] == q) t[p].ch[c] = nq, p = t[p].par;
                } 
            }
            f[np] = 1;
            mp[np] = t[np].val;
            last = np;
        }
    } using namespace SAM;
    struct Segment_Tree {
        int tree[N << 2], tag[N << 2]; 
        Segment_Tree() { memset(tag, 0x3f3f, sizeof(tag)); memset(tree, 0x3f3f, sizeof(tree)); }
        void pushdown(int x)
        {
            tag[x << 1] = min(tag[x << 1], tag[x]);
            tag[x << 1 | 1] = min(tag[x << 1 | 1], tag[x]);
            tree[x << 1] = min(tree[x << 1], tag[x]);
            tree[x << 1 | 1] = min(tree[x << 1 | 1], tag[x]);
            tag[x] = inf; 
        }
        void update(int l, int r, int x, int a, int b, int d)
        {
            if(l > b || r < a) return;
            if(l >= a && r <= b) 
            {
                tree[x] = min(tree[x], d);
                tag[x] = min(tag[x], d);
                return;
            }
            pushdown(x);
            int mid = (l + r) >> 1;
            update(l, mid, x << 1, a, b, d);
            update(mid + 1, r, x << 1 | 1, a, b, d);
            tree[x] = min(tree[x << 1], tree[x << 1 | 1]);
        }
        int query(int l, int r, int x, int pos)
        {
            if(l == r) return tree[x];
            pushdown(x);
            int mid = (l + r) >> 1;
            if(pos <= mid) return query(l, mid, x << 1, pos);
            else return query(mid + 1, r, x << 1 | 1, pos);
        }
    } A, B;
    int main()
    {
        scanf("%s", s + 1);
        n = strlen(s + 1);
        for(int i = 1; i <= n; ++i) extend(s[i] - 'a');
        for(int i = 1; i <= sz; ++i) ++c[t[i].val];
        for(int i = 1; i <= sz; ++i) c[i] += c[i - 1];
        for(int i = 1; i <= sz; ++i) a[c[t[i].val]--] = i;
        for(int i = sz; i; --i) 
        {
            f[t[a[i]].par] += f[a[i]];
            mp[t[a[i]].par] = max(mp[t[a[i]].par], mp[a[i]]);
        }
        for(int i = 1; i <= sz; ++i) if(f[i] == 1) 
        {
            int l = t[t[i].par].val, r = t[i].val; 
            A.update(1, n, 1, mp[i] - l, mp[i], l + 1);
            B.update(1, n, 1, mp[i] - r + 1, mp[i] - l, mp[i] + 1);
        }
        for(int i = 1; i <= n; ++i) printf("%d
    ", min(A.query(1, n, 1, i), B.query(1, n, 1, i) - i));
        return 0;
    }
    View Code
  • 相关阅读:
    USACO Spinning Wheels
    USACO Agri-Net
    NOIP 2009 最优贸易
    USACO Cow Contest
    USACO Subset Sums
    USACO Cow Cars
    USACO Making the Grade
    NOIP 2008 传纸条
    NOIP 2000 方格取数
    NOIP 1999 导弹拦截
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7887515.html
Copyright © 2011-2022 走看看