• 广义后缀自动机(广义 SAM)【模板】


    题目链接

      GSAM:求N个串的本质不同的子串的数目。

      于是,如果单串的SAM肯定就不够用了,所以我们不妨利用构造一棵字典树,然后在字典树上利用BFS去跑SAM来实现GSAM。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    #include <unordered_map>
    #include <unordered_set>
    #define lowbit(x) ( x&(-x) )
    #define pi 3.141592653589793
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    #define pii pair<int, int>
    #define MP(a, b) make_pair(a, b)
    using namespace std;
    typedef unsigned long long ull;
    typedef unsigned int uit;
    typedef long long ll;
    const int maxS = 1e6 + 7;
    int N, tot, root;
    struct Trie
    {
        int c, fa;
        int nex[26];
    } t[maxS];
    char s[maxS];
    void Insert()
    {
        int len = (int)strlen(s);
        int rt = root;
        for(int i = 0, id; i < len; i++)
        {
            id = s[i] - 'a';
            if(!t[rt].nex[id])
            {
                t[rt].nex[id] = ++tot;
                t[tot].fa = rt;
                t[tot].c = id;
            }
            rt = t[rt].nex[id];
        }
    }
    struct SAM
    {
        struct state
        {
            int len, link, next[30];
        } st[maxS << 1];
        int siz = 1;
        void init()
        {
            siz = 1;
            st[1].len = 0;
            st[1].link = 0;
            siz++;
        }
        int extend(int c, int last)
        {
            int cur = siz++;
            st[cur].len = st[last].len + 1;
            int p = last;
            while (p != 0 && !st[p].next[c])
            {
                st[p].next[c] = cur;
                p = st[p].link;
            }
            if (p == 0)
            {
                st[cur].link = 1;
            }
            else
            {
                int q = st[p].next[c];
                if (st[p].len + 1 == st[q].len)
                {
                    st[cur].link = q;
                }
                else
                {
                    int clone = siz++;
                    st[clone].len = st[p].len + 1;
                    memcpy(st[clone].next, st[q].next, sizeof(st[q].next));
                    st[clone].link = st[q].link;
                    while (p != 0 && st[p].next[c] == q)
                    {
                        st[p].next[c] = clone;
                        p = st[p].link;
                    }
                    st[q].link = st[cur].link = clone;
                }
            }
            return last = cur;
        }
    } sam;
    int pos[maxS];
    int main()
    {
        scanf("%d", &N);
        tot = 0;
        root = ++tot;
        for(int i=1; i<=N; i++)
        {
            scanf("%s", s);
            Insert();
        }
        sam.init();
        queue<int> Q;
        for(int i=0; i<26; i++) if(t[root].nex[i]) Q.push(t[root].nex[i]);
        pos[root] = 1;
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop();
            pos[u] = sam.extend(t[u].c, pos[t[u].fa]);
            for(int i=0; i<26; i++) if(t[u].nex[i]) Q.push(t[u].nex[i]);
        }
        ll ans = 0;
        for(int i=2; i<=sam.siz; i++) ans += sam.st[i].len - sam.st[sam.st[i].link].len;
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    Windows CMD中 find命令(字符串查找)
    网络地址转换静态NAT
    网络地址转换静态NAT
    Android 的暗示 hint 用法
    Android 的暗示 hint 用法
    SQL Server 扩展事件
    SQL Server 扩展事件
    SqlServer中Exists的使用
    SqlServer中Exists的使用
    数据库还原,System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权。
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/13695240.html
Copyright © 2020-2023  润新知