This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub ttamx/cp-library
#include "string/suffix-array.hpp"
#pragma once #include "data-structure/sparse-table.hpp" #include "group/monoid/min.hpp" /** * Author: Teetat T. * Date: 2024-06-14 * Description: Suffix Array. */ template<class STR> struct SuffixArray{ int n; vector<int> sa,isa,lcp; SparseTable<MinMonoid<int>> st; SuffixArray(){} SuffixArray(const STR &s){init(s);} void init(const STR &s){ n=(int)s.size(); sa=isa=lcp=vector<int>(n+1); sa[0]=n; iota(sa.begin()+1,sa.end(),0); sort(sa.begin()+1,sa.end(),[&](int i,int j){return s[i]<s[j];}); for(int i=1;i<=n;i++){ int x=sa[i-1],y=sa[i]; isa[y]=i>1&&s[x]==s[y]?isa[x]:i; } for(int len=1;len<=n;len<<=1){ vector<int> ps(sa),pi(isa),pos(n+1); iota(pos.begin(),pos.end(),0); for(auto i:ps)if((i-=len)>=0)sa[pos[isa[i]]++]=i; for(int i=1;i<=n;i++){ int x=sa[i-1],y=sa[i]; isa[y]=pi[x]==pi[y]&&pi[x+len]==pi[y+len]?isa[x]:i; } } for(int i=0,k=0;i<n;i++){ for(int j=sa[isa[i]-1];j+k<n&&s[j+k]==s[i+k];k++); lcp[isa[i]]=k; if(k)k--; } st.init(lcp); } int get_lcp(int i,int j){ if(i==j)return n-i; auto [l,r]=minmax(isa[i],isa[j]); return st.query(l+1,r); } };
#line 2 "data-structure/sparse-table.hpp" /** * Author: Teetat T. * Date: 2024-06-12 * Description: Sparse Table class. */ template<class Monoid> struct SparseTable{ using T = typename Monoid::value_type; int n; vector<vector<T>> t; SparseTable(){} SparseTable(const vector<T> &a){init(a);} void init(const vector<T> &a){ n=(int)a.size(); int lg=31-__builtin_clz(n); t.assign(lg+1,vector<T>(n,Monoid::unit())); t[0]=a; for(int i=0;i<lg;i++){ for(int j=0;j+(2<<i)<=n;j++){ t[i+1][j]=Monoid::op(t[i][j],t[i][j+(1<<i)]); } } } T query(int l,int r){ int lg=31-__builtin_clz(r-l+1); return Monoid::op(t[lg][l],t[lg][r-(1<<lg)+1]); } }; #line 2 "group/monoid/min.hpp" /** * Author: Teetat T. * Date: 2024-04-14 * Description: Min Monoid class. */ template<class T> struct MinMonoid{ using value_type = T; static constexpr T op(const T &x,const T &y){return min(x,y);} static constexpr T unit(){return numeric_limits<T>::max();} }; #line 4 "string/suffix-array.hpp" /** * Author: Teetat T. * Date: 2024-06-14 * Description: Suffix Array. */ template<class STR> struct SuffixArray{ int n; vector<int> sa,isa,lcp; SparseTable<MinMonoid<int>> st; SuffixArray(){} SuffixArray(const STR &s){init(s);} void init(const STR &s){ n=(int)s.size(); sa=isa=lcp=vector<int>(n+1); sa[0]=n; iota(sa.begin()+1,sa.end(),0); sort(sa.begin()+1,sa.end(),[&](int i,int j){return s[i]<s[j];}); for(int i=1;i<=n;i++){ int x=sa[i-1],y=sa[i]; isa[y]=i>1&&s[x]==s[y]?isa[x]:i; } for(int len=1;len<=n;len<<=1){ vector<int> ps(sa),pi(isa),pos(n+1); iota(pos.begin(),pos.end(),0); for(auto i:ps)if((i-=len)>=0)sa[pos[isa[i]]++]=i; for(int i=1;i<=n;i++){ int x=sa[i-1],y=sa[i]; isa[y]=pi[x]==pi[y]&&pi[x+len]==pi[y+len]?isa[x]:i; } } for(int i=0,k=0;i<n;i++){ for(int j=sa[isa[i]-1];j+k<n&&s[j+k]==s[i+k];k++); lcp[isa[i]]=k; if(k)k--; } st.init(lcp); } int get_lcp(int i,int j){ if(i==j)return n-i; auto [l,r]=minmax(isa[i],isa[j]); return st.query(l+1,r); } };