:warning: SuffixAutomaton
(string/suffix_automaton.hpp)

Code

#pragma once
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<set>

/**
 * @brief SuffixAutomaton
 */

struct suffix_automaton{
    struct node;
    using np=node*;
    struct node{
        int len,id;
        std::map<char,np> ch;
        np link=nullptr;
        node(int len,int id):len(len),id(id){}
    };
    std::vector<np>list;
    np root=new node(0,0);
    np t=root;
    suffix_automaton(std::string s){
        list.emplace_back(root);
        for(auto c:s)add(c);
        dfs(root);
        std::reverse(tsort.begin(),tsort.end());
    }
    void add(char c){
        np cur=new node(t->len+1,list.size());
        list.emplace_back(cur);
        for(;t&&!t->ch.count(c);t=t->link)t->ch[c]=cur;
        if(!t)cur->link=root;
        else{
            np p=t,q=p->ch[c];
            if(q->len==p->len+1)cur->link=q;
            else{
                np clone=new node(*q);
                clone->len=p->len+1;
                clone->id=list.size();
                list.emplace_back(clone);
                for(;p&&p->ch[c]==q;p=p->link)p->ch[c]=clone;
                q->link=cur->link=clone;
            }
        }
        t=cur;
    }
    std::vector<int>tsort;
    std::set<np>visited;
    void dfs(np cur){
        if(visited.count(cur))return;
        visited.insert(cur);
        for(auto e:cur->ch)dfs(e.second);
        tsort.emplace_back(cur->id);
    }
    long long size(){
        std::vector<long long>dp(list.size(),0);
        long long ret=0;
        dp[0]=1;
        for(int i:tsort){
            ret+=dp[i];
            for(auto e:list[i]->ch){
                dp[e.second->id]+=dp[i];
            }
        }
        return ret-1;
    }
};
#line 2 "string/suffix_automaton.hpp"
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<set>

/**
 * @brief SuffixAutomaton
 */

struct suffix_automaton{
    struct node;
    using np=node*;
    struct node{
        int len,id;
        std::map<char,np> ch;
        np link=nullptr;
        node(int len,int id):len(len),id(id){}
    };
    std::vector<np>list;
    np root=new node(0,0);
    np t=root;
    suffix_automaton(std::string s){
        list.emplace_back(root);
        for(auto c:s)add(c);
        dfs(root);
        std::reverse(tsort.begin(),tsort.end());
    }
    void add(char c){
        np cur=new node(t->len+1,list.size());
        list.emplace_back(cur);
        for(;t&&!t->ch.count(c);t=t->link)t->ch[c]=cur;
        if(!t)cur->link=root;
        else{
            np p=t,q=p->ch[c];
            if(q->len==p->len+1)cur->link=q;
            else{
                np clone=new node(*q);
                clone->len=p->len+1;
                clone->id=list.size();
                list.emplace_back(clone);
                for(;p&&p->ch[c]==q;p=p->link)p->ch[c]=clone;
                q->link=cur->link=clone;
            }
        }
        t=cur;
    }
    std::vector<int>tsort;
    std::set<np>visited;
    void dfs(np cur){
        if(visited.count(cur))return;
        visited.insert(cur);
        for(auto e:cur->ch)dfs(e.second);
        tsort.emplace_back(cur->id);
    }
    long long size(){
        std::vector<long long>dp(list.size(),0);
        long long ret=0;
        dp[0]=1;
        for(int i:tsort){
            ret+=dp[i];
            for(auto e:list[i]->ch){
                dp[e.second->id]+=dp[i];
            }
        }
        return ret-1;
    }
};
Back to top page