一些模板
\(\texttt{header}\)
namespace myheader{
#ifndef ONLINE_JUDGE
#define ENABLE_DEBUG
#define ENABLE_FILEREDIR
#endif
#define ENABLE_FREAD
#ifdef ENABLE_FREAD
char buf[1<<20],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))?EOF:*p1++)
#endif
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<int,int> pii;
#ifdef ENABLE_FILEREDIR
struct fredir{
fredir(const string str){
freopen((str+(string)".in").c_str(),"r",stdin);
freopen((str+(string)".out").c_str(),"w",stdout);
}
}redir("emotion");
#endif
#define fi first
#define se second
template<typename T>
ostream& operator<<(ostream& os,vector<T> cur){
if(cur.empty()) return os<<"{}";
os<<'{'<<cur.front();
for(size_t i=1;i<cur.size();++i) os<<','<<cur[i];
return os<<'}';
}
template<typename T>
void chmn(T& x,T v){if(x>v) x=v;}
template<typename T>
void chmx(T& x,T v){if(x<v) x=v;}
template<typename T>
void _debug(const char *str,T x){
#ifdef ENABLE_DEBUG
cerr<<str<<'='<<x<<endl;
#endif
}
template<typename T,typename... Ts>
void _debug(const char *str,T x,Ts... y){
#ifdef ENABLE_DEBUG
while(*str!=',') cerr<<*str++;
cerr<<'='<<x<<',';
_debug(str+1,y...);
#endif
}
#define debug(...) _debug(#__VA_ARGS__,__VA_ARGS__)
template<typename T=int>
T read(){
char c=getchar();bool f=0;T x=0;
while(c<48||c>57) f|=(c=='-'),c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
if(f) return -x;
return x;
}
template<typename T>
void read(T& x){
char c=getchar();bool f=0;x=0;
while(c<48||c>57) f|=(c=='-'),c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
if(f) x=-x;
}
template<typename T,typename... Ts>
void read(T& x,Ts&... y){read(x);read(y...);}
}
\(\texttt{modint}\)
struct mint{int v;mint(int x=0):v(x){}};
mint operator+(const mint x,const mint y){return (x.v+y.v)%P;}
mint operator-(const mint x,const mint y){return (x.v+P-y.v)%P;}
mint operator*(const mint x,const mint y){return 1ll*x.v*y.v%P;}
mint operator/(const mint x,const mint y){
int b=P-2;mint r=x,a=y;
while(b){if(b&1) r=r*a;a=a*a;b>>=1;}
return r;
}
mint operator-(const mint x){return P-x;}
mint operator+=(mint &x,const mint y){return x=x+y;}
mint operator-=(mint &x,const mint y){return x=x-y;}
mint operator*=(mint &x,const mint y){return x=x*y;}
mint operator/=(mint &x,const mint y){return x=x/y;}
\(\texttt{read}\)
int read(){
char c=getchar();int x=0;
while(c<48||c>57) c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
return x;
}
int read(){
char c=getchar();int x=0;bool f=0;
while(c<48||c>57) f|=(c=='-'),c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
if(f) return -x;
return x;
}
\(\texttt{fastread}\)
#define gec() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
char c=gec();int x=0;
while(c<48||c>57) c=gec();
do x=(x<<1)+(x<<3)+(c^48),c=gec();
while(c>=48&&c<=57);
return x;
}
#define gec() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
char c=gec();int x=0;bool f=0;
while(c<48||c>57) f|=(c=='-'),c=gec();
do x=(x<<1)+(x<<3)+(c^48),c=gec();
while(c>=48&&c<=57);
if(f) return -x;
return x;
}
\(\texttt{Suffix Automaton}\)
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1000003;
char s[N];
int tr[N][26],sz[N],len[N],link[N];
int buc[N],ord[N];
int last,cnt,n;
void extend(int c){
int cur=++cnt,p=last;last=cur;
len[cur]=len[p]+1;sz[cur]=1;
while(p&&!tr[p][c]) tr[p][c]=cur,p=link[p];
if(!p) {link[cur]=1;return;}
int q=tr[p][c];
if(len[q]==len[p]+1) {link[cur]=q;return;}
int clone=++cnt;
len[clone]=len[p]+1;
link[clone]=link[q];
memcpy(tr[clone],tr[q],104);
link[q]=link[cur]=clone;
while(p&&tr[p][c]==q) tr[p][c]=clone,p=link[p];
}
void build(){
last=cnt=1;
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;++i) extend(s[i]-'a');
for(int i=1;i<=cnt;++i) ++buc[len[i]];
for(int i=1;i<=n;++i) buc[i]+=buc[i-1];
for(int i=cnt;i;--i) ord[buc[len[i]]--]=i;
for(int i=cnt;i;--i) sz[link[ord[i]]]+=sz[ord[i]];
}
平时能自己写就自己写吧。
\(\texttt{Suffix Array}\)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=200003;
char s[N];
int n,w,p;
int buc[N],sa[N],rk[N],ork[N],id[N],h[N];
bool cmp(int x,int y){return ork[x]==ork[y]&&ork[x+w]==ork[y+w];};
void get_sa(int m){
memset(buc+1,0,m<<2);
for(int i=1;i<=n;++i) ++buc[rk[i]=s[i]];
for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
for(int i=n;i;--i) sa[buc[rk[i]]--]=i;
for(p=0,w=1;;w<<=1,m=p,p=0){
for(int i=n;i>n-w;--i) id[++p]=i;
for(int i=1;i<=n;++i) if(sa[i]>w) id[++p]=sa[i]-w;
memset(buc+1,0,m<<2);
for(int i=1;i<=n;++i) ++buc[rk[id[i]]];
for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
for(int i=n;i;--i) sa[buc[rk[id[i]]]--]=id[i];
memcpy(ork+1,rk+1,n<<2);
p=rk[sa[1]]=1;
for(int i=2;i<=n;++i) rk[sa[i]]=cmp(sa[i],sa[i-1])?p:++p;
if(p==n) break;
}
for(int i=1,k=0;i<=n;++i){
if(rk[i]==1) {k=0;continue;}
if(k) --k;
while(i+k<=n&&sa[rk[i]-1]+k<=n&&s[i+k]==s[sa[rk[i]-1]+k]) ++k;
h[rk[i]-1]=k;
}
}
感觉比 \(\texttt{SAM}\) 难记,平常多写写吧。