zoukankan      html  css  js  c++  java
  • JJM

    我的头文件

    #include <bits/stdc++.h>
    #define rep(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define debug(a) cerr<<#a<<"=="<<a<<endl
    #define iout(x) printf("%d
    ",x)
    #define lout(x) printf("%lld
    ",x)
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    using namespace std;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int, int> PII;
    const int mod=1e9+7;
    template<typename T> inline void read (T &x) {
        x = 0; T f = 1;
        char ch;
        do {
            ch = getchar(); if (ch == '-') f = -1;
        } while (ch < '0' || ch > '9');
        do x = x * 10 + ch - '0', ch = getchar();
        while (ch <= '9' && ch >= '0'); x *= f;
    }
    
    template<typename A, typename B> inline void read (A &x, B &y) {read (x);read (y);}
    template<typename A, typename B, typename C> inline void read (A &x, B &y, C &z) {read (x);read (y);read (z);}
    template<typename A, typename B, typename C, typename D> inline void read (A &x, B &y, C &z, D &w) {read (x);read (y);read (z);read (w);}
    template<typename A,typename B> inline A fexp(A x,B p){A ans=1;for(;p;p>>=1,x=1LL*x*x%mod)if(p&1)ans=1LL*ans*x%mod;return ans;}
    template<typename A,typename B> inline A fexp(A x,B p,A mo){A ans=1;for(;p;p>>=1,x=1LL*x*x%mo)if(p&1)ans=1LL*ans*x%mo;return ans;}
    //head
    

    suffix array

    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int maxn = 200000 + 100;
    
    int sa[maxn];
    int t1[maxn], t2[maxn], c[maxn];
    int rak[maxn], height[maxn];
    int r[maxn];
    //待排序的字符串放在s数组中,从r[0]到r[n-1],长度为n,且最大值小于m,
    //除r[n-1]外的所有r[i]都大于0,r[n-1]=0
    //函数结束以后结果放在sa数组中
    void build_sa(int r[], int n, int m) {
        int i, j, p, *x = t1, *y = t2;
        //第一轮基数排序,如果s的最大值很大,可改为快速排序
        for (i = 0; i < m; i++)c[i] = 0;
        for (i = 0; i < n; i++)c[x[i] = r[i]]++;
        for (i = 1; i < m; i++)c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--)sa[--c[x[i]]] = i;
        for (j = 1; j <= n; j <<= 1) {
            p = 0;
            //直接利用sa数组排序第二关键字
            for (i = n - j; i < n; i++)y[p++] = i; //后面的j个数第二关键字为空的最小
            for (i = 0; i < n; i++)if (sa[i] >= j)y[p++] = sa[i] - j;
            //这样数组y保存的就是按照第二关键字排序的结果
            //基数排序第一关键字
            for (i = 0; i < m; i++)c[i] = 0;
            for (i = 0; i < n; i++)c[x[y[i]]]++;
            for (i = 1; i < m; i++)c[i] += c[i - 1];
            for (i = n - 1; i >= 0; i--)sa[--c[x[y[i]]]] = y[i];
            //根据sa和x数组计算新的x数组
            swap(x, y);
            p = 1; x[sa[0]] = 0;
            for (i = 1; i < n; i++)
                x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? p - 1 : p++;
            if (p >= n)break;
            m = p; //下次基数排序的最大值
        }
    }
    void getHeight(int r[], int n) {
        int i, j, k = 0;
        for (i = 0; i <= n; i++)rak[sa[i]] = i;
        for (i = 0; i < n; i++) {
            if (k)k--;
            j = sa[rak[i] - 1];
            while (r[i + k] == r[j + k])k++;
            height[rak[i]] = k;
        }
    }
    char str[maxn];
    
    
    int main() {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%s", str);
            int n = strlen(str);
            for (int i = 0; i <= n; i++)r[i] = str[i];
            build_sa(r, n + 1, 128);
            getHeight(r, n);
            int ans = n * (n + 1) / 2;
            for (int i = 2; i <= n; i++)ans -= height[i];
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    

    SAM

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    const int N = 100010;//点的数目
    // 空间复杂度不多余2*n
    // 下表为0也使用
    struct SAM {
        struct Node {
            int ch[26];
            int f, len;
            void init() { f = -1, len = 0; memset(ch, 0xff, sizeof (ch));}
        };
        Node sa[N<<1];
        int idx, last;
        void init() {
            idx = last = 0;
            sa[idx++].init();
        }
        int newnode() {
            sa[idx].init();
            return idx++;
        }
        void add(int c) {
            int end = newnode();
            int tmp = last;
            sa[end].len = sa[last].len + 1;
            for ( ; tmp != -1 && sa[tmp].ch[c] == -1; tmp = sa[tmp].f) {
                sa[tmp].ch[c] = end;
            }
            if (tmp == -1) sa[end].f = 0; // 所有的上一轮可接受点都没有指向字符c的孩子节点
            else {
                int nxt = sa[tmp].ch[c];
                if (sa[tmp].len + 1 == sa[nxt].len) sa[end].f = nxt; // 如果可接受点有向c的转移,且长度只加1,那么该孩子可以替代当前的end,并且end的双亲指向该孩子
                else {
                    int np = newnode();
                    sa[np] = sa[nxt];
                    sa[np].len = sa[tmp].len + 1;
                    sa[end].f = sa[nxt].f = np;
                    for (; tmp != -1 && sa[tmp].ch[c] == nxt; tmp = sa[tmp].f) {
                        sa[tmp].ch[c] = np;
                    }
                }
            }
            last = end;
        }
    };
    void upd(int& x,int y) {
        if(y>x) x=y;
    }
    SAM sam;
    char s1[N],s2[N];
    int main() {
        freopen("in.txt","r",stdin);            
        while(scanf("%s%s",s1,s2)!=EOF) {
            int len1=strlen(s1);
            int len2=strlen(s2);
            sam.init();
            for(int i=0;i<len1;i++) {
                sam.add(s1[i]-'a');
            }
            int p=0,rms=0;
            int ans=0;
            for(int i=0;i<len2;i++) {
                int x=s2[i]-'a';
                if(sam.sa[p].ch[x]!=-1) {
                    rms++;
                    p=sam.sa[p].ch[x];
                }else {
                    for(;p!=-1&&sam.sa[p].ch[x]==-1;p=sam.sa[p].f);
                    if(p==-1) rms=0,p=0;
                    else {
                        rms=sam.sa[p].len+1;
                        p=sam.sa[p].ch[x];
                    }
                }
                upd(ans,rms);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    spring boot所有配置
    Hibernate validator的一些额外特性
    相似序列搜索
    时间序列异常检测
    基于结构的距离度量
    jupyterlab的启动404error问题
    爬虫-Chrome-问题1
    厘清重要概念的内涵与外延
    六)定时任务持久化
    公钥私钥
  • 原文地址:https://www.cnblogs.com/foreignbill/p/7751443.html
Copyright © 2011-2022 走看看