zoukankan      html  css  js  c++  java
  • 后缀自动机(SAM) 合集

    先上模板

    int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc];
    LL num[maxn << 1];
    int size,last;
    void Init(){
        size = last = 1;
    }
    void insert(char c){
        int s = c - 'a';
        int p = last,np = ++size;last = np; num[np] = 1; //主链结点出现次数 + 1
        len[np] = len[p] + 1;
        for(;p && !son[p][s]; p = fa[p]) son[p][s] = np;
        if(!p) fa[np] = 1;
        else{
            int q = son[p][s];
            if(len[p] + 1 == len[q]) fa[np] = q;
            else{
                int nq = ++size; len[nq] = len[p] + 1;
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[nq] = fa[q]; fa[q] = fa[np] = nq;
                for(;son[p][s] == q && p;p = fa[p]) son[p][s] = nq;
            }
        }
    }
    void insert(char *s){
        Init();
        for(int i = 0; s[i] ; i ++) insert(s[i]);
    }
    View Code

    9.10 update

    P3804 【模板】后缀自动机

    dfs parent树可以统计每个子串出现的次数

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 1e6 + 10;
    const int maxc = 26;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc];
    LL num[maxn << 1];
    int size,last;
    void Init(){
        size = last = 1;
    }
    void insert(char c){
        int s = c - 'a';
        int p = last,np = ++size;last = np; num[np] = 1; 
        len[np] = len[p] + 1;
        for(;p && !son[p][s]; p = fa[p]) son[p][s] = np;
        if(!p) fa[np] = 1;
        else{
            int q = son[p][s];
            if(len[p] + 1 == len[q]) fa[np] = q;
            else{
                int nq = ++size; len[nq] = len[p] + 1;
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[nq] = fa[q]; fa[q] = fa[np] = nq;
                for(;son[p][s] == q && p;p = fa[p]) son[p][s] = nq;
            }
        }
    }
    void insert(char *s){
        Init();
        for(int i = 0; s[i] ; i ++) insert(s[i]);
    }
    char str[maxn];
    struct Edge{
        int to,next;
    }edge[maxn << 1];
    int head[maxn << 1],tot;
    void init(){
        for(int i = 0; i <= size; i ++) head[i] = -1;
        tot = 0;
    }
    void add(int u,int v){
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void dfs(int t){
        for(int i = head[t]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            dfs(v);
            num[t] += num[v];
        }
    }
    int main(){
        scanf("%s",str);
        insert(str); init();
        for(int i = 2; i <= size; i ++) add(fa[i],i);
        dfs(1);
        LL ans = 0;
        for(int i = 2; i <= size; i ++) if(num[i] != 1)ans = max(ans,len[i] * num[i]);
        Prl(ans);
        return 0;
    }
    View Code

    P1368 工艺

    最小表示法,将原串倍增一遍插入,SAM上直接寻找长度为N的字典序最小的路径

    因为是倍增了一遍,脑补证明往任意点出发必定能找到长度至少为N的路径,所以甚至不需要dfs,直接跑即可

    const int maxn = 6e5 + 10;
    int N,M,K;
    int len[maxn << 1],fa[maxn << 1];
    map<int,int>son[maxn << 1];
    int size,last;
    void Init(){
        size = last = 1;
    }
    inline void insert(int c){
        int p = last,np = ++size; last = np;
        len[np] = len[p] + 1;
        for(;p && !son[p].count(c); p = fa[p]) son[p][c] = np;
        if(!p) fa[np] = 1;
        else{
            int q = son[p][c];
            if(len[p] + 1 == len[q]) fa[np] = q;
            else{
                int nq = ++size; len[nq] = len[p] + 1;
                son[nq] = son[q];
                fa[nq] = fa[q]; fa[q] = fa[np] = nq;
                for(;son[p][c] == q && p; p = fa[p]) son[p][c] = nq;
            }
        }
    }
    int a[maxn];
    int main(){
        Sca(N); Init();
        for(int i = 1; i <= N ; i ++) insert(a[i] = read());
        for(int i = 1; i <= N ; i ++) insert(a[i]);
        int t = 1;
        for(int i = 1; i <= N ; i ++){
            printf("%d ",son[t].begin()->first);
            t = son[t].begin()->second;
        }
        return 0;
    }
    View Code

    K小子串

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 5e5 + 10;
    const int maxc = 26;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc];
    int size,last;
    int num[maxn << 1];
    void Init(){
        size = last = 1;
    }
    void insert(char c){
        int s = c - 'a';
        int p = last,np = ++size;last = np;num[np] = 1;
        len[np] = len[p] + 1;
        for(;p && !son[p][s]; p = fa[p]) son[p][s] = np;
        if(!p) fa[np] = 1;
        else{
            int q = son[p][s];
            if(len[p] + 1 == len[q]) fa[np] = q;
            else{
                int nq = ++size; len[nq] = len[p] + 1;
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[nq] = fa[q]; fa[q] = fa[np] = nq;
                for(;son[p][s] == q && p; p = fa[p]) son[p][s] = nq;
            }
        }
    }
    void insert(char *s){
        Init();
        for(int i = 0;s[i]; i ++) insert(s[i]);
    }
    char str[maxn];
    int tmp[maxn << 1],A[maxn << 1];
    int sum[maxn << 1];
    void dfs(int t,int k){
        if(k <= num[t]) return;
        k -= num[t];
        for(int i = 0 ; i < 26; i ++){
            if(!son[t][i]) continue;
            int v = son[t][i];
            if(sum[v] >= k){
                printf("%c",i + 'a');
                dfs(v,k);
                return;
            }
            k -= sum[v];
        }
    }
    int main(){
        scanf("%s",str); 
        insert(str); 
        for(int i = 1; i <= size; i ++) tmp[len[i]]++;
        for(int i = 1; i <= size; i ++) tmp[i] += tmp[i - 1];
        for(int i = 1; i <= size; i ++) A[tmp[len[i]]--] = i;
        for(int i = size; i >= 1; i --) num[fa[A[i]]] += num[A[i]];
        int op = read(),k = read();
        for(int i = 1; i <= size; i ++) sum[i] = op?num[i]:num[i] = 1;
        sum[1] = num[1] = 0;
        for(int i = size; i >= 1; i --){
            for(int j = 0 ; j < 26; j ++){
                if(son[A[i]][j]) sum[A[i]] += sum[son[A[i]][j]];
            }
        }
        if(sum[1] < k) puts("-1");
        else dfs(1,k);
        return 0;
    }
    View Code

    留坑

  • 相关阅读:
    vue中用解构赋值的方法引入组件
    es6--promise
    VUE设置浏览器icon图标
    vue项目之购物车
    vue之组件通信
    hbulider 快捷键
    Redis详解(3)--5大数据类型
    Redis详解(1)--redis简介与安装
    Redis详解(2)--redis配置文件介绍
    Python面试综合--web相关
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/11502775.html
Copyright © 2011-2022 走看看