zoukankan      html  css  js  c++  java
  • P4081 [USACO17DEC]Standing Out from the Herd P

    题面

    自己去看吧

    题解

    明显的广义后缀自动机, 关键怎么算, 只能按字符串出遍历每个节点

    再根据link去标记节点, 最后根据标记去算贡献

    struct EXSAM { //trie一样的空间 N * M, 再建自动机为 N * M << 1
        static const int N = 1e5 + 5, M = 26, C = 'a', NUM = 15;//N字串总长度,NUM字符串个数
        struct Node { int len, fa, ne[M]; } tr[N << 1];
        int tot, mxlen, tax[N << 1], rk[N << 1];
        int newNode() { return memset(tr[++tot].ne, 0, sizeof tr[0].ne), tot; }
        void init() { 
            memset(tr[0].ne, 0, sizeof tr[0].ne); 
            tot = mxlen = 0; tr[0].fa = -1;
        }
        int insertSAM(int las, int ch) {
            int cur = tr[las].ne[ch], p = tr[las].fa;
            tr[cur].len = tr[las].len + 1;
            for (; p != -1 && !tr[p].ne[ch]; p = tr[p].fa) tr[p].ne[ch] = cur;
            if (p == -1) return tr[cur].fa = 0, cur;
            int q = tr[p].ne[ch];
            if (tr[p].len + 1 == tr[q].len) return tr[cur].fa = q, cur;
            int nq = ++tot; tr[nq].len = tr[p].len + 1; tr[nq].fa = tr[q].fa;
            rep (i, 0, M - 1) tr[nq].ne[i] = tr[tr[q].ne[i]].len ? tr[q].ne[i] : 0;
            for (; p != -1 && tr[p].ne[ch] == q; p = tr[p].fa) tr[p].ne[ch] = nq;
            return tr[cur].fa = tr[q].fa = nq, cur;
        }
        int insertTrie(int cur, int ch) {
            if (!tr[cur].ne[ch]) tr[cur].ne[ch] = newNode();
            return tr[cur].ne[ch];
        }
        int insert(const char *s) {
            int len = 0;
            for (int& i = len, p = 0; s[i]; p = insertTrie(p, s[i++] - C));
            return umax(mxlen, len), len;
        }
        void build() {
            queue<pair<int, int>> q;
            rep (i, 0, M - 1) if (tr[0].ne[i]) q.push({ i, 0 });
            while (!q.empty()) {
                PII it = q.front(); q.pop();
                int las = insertSAM(it.se, it.fi);
                rep (i, 0, M - 1) if (tr[las].ne[i]) q.push({ i, las });
            }
        }
        int tag[N << 1], ans[N];
        void dfs(int p, int id) {
            for (; p != -1 && tag[p] != id && tag[p] != -1; p = tr[p].fa) tag[p] = tag[p] ? -1 : id;
        }
        void difsub(char *s, int* len, int n) {
            rep (i, 1, n) for (int j = len[i - 1], p = tr[0].ne[s[j] - C]; j < len[i]; p = tr[p].ne[s[++j] - C]) dfs(p, i);
            rep (i, 0, tot) if (tag[i] != -1) ans[tag[i]] += tr[i].len - tr[tr[i].fa].len;
            rep (i, 1, n) cout << ans[i] << '
    ';
        }
    } exSam;
    
    const int N = 1e5 + 5, inf = 0x3f3f3f3f;
    
    int n, m, _, k;
    int len[N], ans[N];
    char s[N];
    
    int main() {
        exSam.init(); read(n);
        rep (i, 1, n) { cin >> s + len[i - 1]; len[i] = exSam.insert(s + len[i - 1]) + len[i - 1]; }
        exSam.build(); exSam.difsub(s, len, n);
        return 0;
    }
    
  • 相关阅读:
    c# 自定义事件和委托
    C#委托之个人理解(转)
    invokeRequired属性和 invoke()方法
    .NET(C#)连接各类数据库
    Mobile Web Development with ASP.NET 2.0
    移动飞信WEB发送服务接口
    4行C#代码打造专业数据库连接配置界面
    domino 中 UniversalID 和NoteID的区别
    VB中preserve的用法
    LOTUS Note ID 剖析
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/14173883.html
Copyright © 2011-2022 走看看