zoukankan      html  css  js  c++  java
  • [hdu4416 Good Article Good sentence]后缀自动机SAM

    题意:给出串A和串集合B={B1,B2,...,Bn},求串A的所有不同子串中不是B中任一串的子串的数目。

    思路:把A和B中所有字符串依次拼接在一起,然后构造后缀自动机,计算每个状态的R集合元素的最大值r,然后统计那些r≤length(A)的状态。hdu不卡时间卡空间,这是最郁闷的。。。导致下面的程序只在本地随机数据没发现错误,提交就MLE。

    #include <bits/stdc++.h>
    using namespace std;
    #define X first
    #define Y second
    #define pb(x) push_back(x)
    #define mp(x, y) make_pair(x, y)
    #define all(a) (a).begin(), (a).end()
    #define mset(a, x) memset(a, x, sizeof(a))
    #define mcpy(a, b) memcpy(a, b, sizeof(b))
    #define cas() int T, cas = 0; cin >> T; while (T --)
    template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
    template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
    typedef long long ll;
    typedef pair<int, int> pii;
    
    #ifndef ONLINE_JUDGE
        #include "local.h"
    #endif
    
    const int N = 6e5 + 7;
    
    int len;
    
    //注意空间为 DOUBLE SIZE
    class SAM {
    public:
        void init() {
            memset(node, 0, sizeof(node));
            sz = last = 0;
            node[0].len = 0;
            node[0].link = -1;
            sz ++;
        }
        void add(char c) {
            int cur = sz ++;
            node[cur].len = node[last].len + 1;
            node[cur].r = node[cur].len;
            int p;
            for (p = last; ~p && !node[p].next[c]; p = node[p].link) {
                node[p].next[c] = cur;
            }
            if (p == -1) node[cur].link = 0;
            else {
                int q = node[p].next[c];
                if (node[p].len + 1 == node[q].len) node[cur].link = q;
                else {
                    int clone = sz ++;
                    node[clone].link = node[q].link;
                    memcpy(node[clone].next, node[q].next, sizeof(node[q].next));
                    node[clone].len = node[p].len + 1;
                    for (; ~p && node[p].next[c] == q; p = node[p].link) {
                        node[p].next[c] = clone;
                    }
                    node[q].link = node[cur].link = clone;
                }
            }
            last = cur;
        }
        int c[N], p[N];
        ll getAns() {
            mset(c, 0);
            for (int i = 0; i < sz; i ++) c[node[i].len] ++;
            for (int i = 1; i <= sz; i ++) c[i] += c[i - 1];
            for (int i = 0; i < sz; i ++) p[-- c[node[i].len]] = i;
            for (int i = sz - 1; i >= 0; i --) {
                int cur = p[i];
                if (cur == 0) continue;
                umax(node[node[cur].link].r, node[cur].r);
            }
            ll ans = 0;
            for (int i = 1; i < sz; i ++) {
                if (node[i].r <= len) ans += node[i].len - node[node[i].link].len;
            }
            return ans;
        }
    private:
        const static int SZ = 27;
        struct State {
            int len, link;
            int r;
            int next[SZ];
        };
        State node[N];
        int sz, last;
    };
    SAM sam;
    char s[N];
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n;
        cas() {
            cin >> n;
            sam.init();
            for (int i = -1; i < n; i ++) {
                scanf("%s", s);
                if (i < 0) len = strlen(s);
                for (int j = 0; s[j]; j ++) {
                    sam.add(s[j] - 'a');
                }
                sam.add(26);
            }
            printf("Case %d: %I64d
    ", ++ cas, sam.getAns());
        }
        return 0;
    }
    

      

  • 相关阅读:
    图片上传-下载-删除等图片管理的若干经验总结3-单一业务场景的完整解决方案
    图片上传-下载-删除等图片管理的若干经验总结2
    HDU 1195 Open the Lock
    HDU 1690 Bus System
    HDU 2647 Reward
    HDU 2680 Choose the best route
    HDU 1596 find the safest road
    POJ 1904 King's Quest
    CDOJ 889 Battle for Silver
    CDOJ 888 Absurdistan Roads
  • 原文地址:https://www.cnblogs.com/jklongint/p/4941496.html
Copyright © 2011-2022 走看看