zoukankan      html  css  js  c++  java
  • 广义后缀自动机模板

    后缀自动机能解决很多单串的问题、但是一旦到了多串的情况、可能就会变得有些棘手

    这个时候你可能会想能不能将多个串一起构建出和单串后缀自动机那样子拥有诸多优美性质的自动机呢?

    答案当然是有的、那就是广义后缀自动机

    对于广义后缀自动机、和普通的后缀自动机写法上有些许不同之处

    大致就是在插入新串的时候、需要把当前状态指针 last 指回 root

    还有一个问题、网上的人们都说广义后缀自动机在新插入节点的时候要判是否已经存在

    这个就造成了代码的迥异

    关于代码、借鉴了这个博客 ==> Click here

    下面仅仅给出模板

    struct General_Suffix_Automaton{
        static const int maxn = ((int)1e5 + 10) * 2;
        static const int Letter = 26;
        int fa[maxn];
        int len[maxn];
        int ch[maxn][Letter];
        int cnt[maxn];
        int tpSum[maxn];
        int tp[maxn];
        int tot;
        int last;
        int mxLen;
    
        inline void init(){
            last = tot = 1;
            len[1] = 0;
            mxLen = 0;
            memset(ch[1], 0, sizeof(ch[1]));
            memset(cnt, 0, sizeof(cnt));
        }
    
        inline void add(int x){
            int p = last;
            if(ch[p][x] && len[ch[p][x]] == len[p] + 1){
                last = ch[p][x];
                return ;
            }///就是在这里特判、下面的代码就基本和普通的SAM差不多了
            int np = ++tot;
            memset(ch[np], 0, sizeof(ch[np]));
            last = np;
            len[np] = len[p] + 1;
            while(p && !ch[p][x]) ch[p][x] = np, p = fa[p];
            if(!p) fa[np] = 1;
            else{
                int q = ch[p][x];
                if(len[q] == len[p] + 1) fa[np] = q;
                else{
                    int nq = ++tot;
                    len[nq] = len[p] + 1;
                    memcpy(ch[nq], ch[q], sizeof(ch[q]));
                    fa[nq] = fa[q];
                    fa[q] = fa[np] = nq;
                    while(p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];
                }
            }
        }
    
        inline void addStr(char * s){
            last = 1;
            int len = strlen(s);
            mxLen = max(mxLen, len);
            for(int i=0; i<len; i++) add(s[i] - 'a'),cnt[last]++;
        }
    
        int deg[maxn];
        inline void toposort(){
            for(int i = 1; i <= mxLen; i++)tpSum[i] = 0;
            for(int i = 1; i <= tot; i++)tpSum[len[i]]++;
            for(int i = 1; i <= mxLen; i++)tpSum[i] += tpSum[i-1];
            for(int i = 1; i <= tot; i++)tp[tpSum[len[i]]--] = i;
            for(int i = tot; i; i--)cnt[fa[tp[i]]] += cnt[tp[i]];
    //        用下面的队列来构造拓扑序也是可以的
    //        queue<int> que;
    //        while(!que.empty()) que.pop();
    //        int tmp = tot;
    //        for(int i=1; i<=tot; i++) deg[fa[i]]++;
    //        for(int i=1; i<=tot; i++) if(!deg[i]) que.push(i);
    //        while(!que.empty()){
    //            int x = que.front();
    //            que.pop();
    //            tp[tmp--] = x;
    //            deg[fa[x]]--;
    //            if(!deg[fa[x]]) que.push(fa[x]);
    //        }
    //        for(int i=tot; i>=1; i--) cnt[fa[tp[i]]] += cnt[tp[i]];
        }
    
        inline void GetAns(char *s){
            ///....
        }
    }sam;
    View Code
  • 相关阅读:
    [转]学习NotesList(Robotium自带的例子)
    [转] Android Test Auto Test Multi Activities
    [转]重新签名Android preinstall APK
    [转]简单介绍如何使用robotium进行自动化测试
    javascript bind函数
    IE中不可遍历的属性
    访问私有变量
    高效地获取XMLhttp对象
    判定IE的各个版本
    CSS Selector の最大の欠点
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9940403.html
Copyright © 2011-2022 走看看