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;
    }
    

      

  • 相关阅读:
    ASCII、Unicode和UTF-8等常见字符编码格式介绍
    pycharm创建脚本头文件模板
    pycharm常用设置项和快捷键
    Genymotion安装apk问题
    [Android测试] Appium的一些坑问题错误解决 与 技巧集锦
    Appium+python自动化测试过程中问题
    python客户端和Appium服务端联调出现的问题解决办法
    移动端自动化测试环境搭建
    "http://127.0.0.1:4723/wd/hub"的解释
    wireshark抓包看ECN
  • 原文地址:https://www.cnblogs.com/jklongint/p/4941496.html
Copyright © 2011-2022 走看看