【模板】字符串
字符串
- 哈希
素数:131
1061
2e6+93
1e7+19
2e7+93
1e9+97
LL(1e16)+61
(1ll<<61)-1
using ULL = unsigned long long;
struct Hash {
static const int mod = 1e9+97;
int x; ULL y; Hash(int x=0):x(x),y(x){} Hash(int x,ULL y):x(x),y(y){}
Hash operator + (const Hash &b) { return {x+b.x<mod?x+b.x:x+b.x-mod, y+b.y}; }
Hash operator - (const Hash &b) { return {x<b.x?x-b.x:x-b.x+mod, y-b.y}; }
Hash operator * (const Hash &b) { return {1ll*x*b.x%mod, y*b.y}; }
bool operator == (const Hash &b) { return x==b.x && y==b.y; }
};
- kmp
// find s in t
// |s| = n, |t| = m
For(i,2,n, j = 0) {
while( j && s[j+1] != s[i] ) j = fail[j];
fail[i] = (j += s[j+1]==s[i]);
}
For(i,1,m, j = 0) { // s[:j] = t[i-j+1:i]
while( j && s[j+1] != t[i] ) j = fail[j];
if( (j += s[j+1]==t[i]) == n ) j = fail[j];
}
- Z function
z[1] = n;
For(i,2,n, l = 0, r = 0) {
if( i <= r ) z[i] = min(z[i-l+1],r-i+1);
while( i+z[i] <= n && s[1+z[i]] == s[i+z[i]] ) ++z[i];
if( ckmax(r,i+z[i]-1) ) l = i;
}
For(i,1,m, l = 0, r = 0) {
int lcp = 0; // lcp(s,t[i:m])
if( i <= r ) lcp = min(z[i-l+1],r-i+1);
while( lcp < n && i+lcp <= m && s[1+lcp] == t[i+lcp] ) ++lcp;
if( ckmax(r,i+lcp-1) ) l = i;
}
- AC 自动机
字符集 \(a\sim z\)
struct {
int ind,t[N][26],fail[N];
Vi que;
void ins(const string &s) {
int u = 0;
for(auto i : s) {
int x = i-'a';
if( !t[u][x] ) t[u][x] = ++ind;
u = t[u][x];
}
}
void bld() {
Rep(i,0,26) if( t[0][i] ) que.pb(t[0][i]);
Rep(i,0,sz(que)) {
int u = que[i];
Rep(i,0,26)
if( t[u][i] ) fail[t[u][i]] = t[fail[u]][i], que.pb(t[u][i]);
else t[u][i] = t[fail[u]][i];
}
}
} ;
- SA
多测需要清空 h[n+1]
namespace SA {
int sa[N],rk[N],id[N],buc[N],h[N];
void bld() {
int m = 128;
For(i,1,n) ++buc[rk[i]=s[i]]; For(i,1,m) buc[i] += buc[i-1];
rFor(i,n,1) sa[buc[rk[i]]--] = i;
for(int w = 1, p = 0; p < n; w <<= 1, m = p) {
p = 0; For(i,n-w+1,n) id[++p] = i;
For(i,1,n) if( sa[i] > w ) id[++p] = sa[i]-w;
memset(buc+1,0,sizeof(int)*m);
For(i,1,n) ++buc[rk[i]]; For(i,1,m) buc[i] += buc[i-1];
rFor(i,n,1) sa[buc[rk[id[i]]]--] = id[i];
p = 0, memcpy(h+1,rk+1,sizeof(int)*n);
auto cmp=[&](int i,int j) { return h[i]==h[j] && h[i+w]==h[j+w]; };
For(i,1,n) rk[sa[i]] = cmp(sa[i],sa[i-1]) ? p : ++p;
}
For(i,1,n, k = 0) {
int j = sa[rk[i]-1];
for(k -= !!k; s[i+k] == s[j+k]; ++k);
h[rk[i]] = k;
}
}
}
- SAM
\(|\Sigma|=26\)
struct SAM {
static const int N = ::N*2;
int ind=1,lst=1,t[N][26],fa[N],len[N],cnt[N],buc[N],id[N];
void extend(int x) {
int p = lst, np = lst = ++ind; len[np] = len[p]+1, cnt[np] = 1;
for(; p && !t[p][x]; p = fa[p]) t[p][x] = np;
if( !p ) fa[np] = 1;
else {
int q = t[p][x];
if( len[p]+1 == len[q] ) fa[np] = q;
else {
int nq = ++ind; len[nq] = len[p]+1;
memcpy(t[nq],t[q],sizeof t[q]);
fa[nq] = fa[q], fa[q] = fa[np] = nq;
for(; p && t[p][x] == q; p = fa[p]) t[p][x] = nq;
}
}
}
void bld() {
For(i,1,ind) ++buc[len[i]];
For(i,1,n) buc[i] += buc[i-1];
rFor(i,ind,1) id[buc[len[i]]--] = i;
rFor(i,ind,2) cnt[fa[id[i]]] += cnt[id[i]];
}
} sam;
- 广义 SAM
\(|\Sigma|=26\)
struct SAM {
static const int N = ::N * 2;
int ind=1,t[N][26],fa[N],len[N];
int extend(int p,int x) {
if( t[p][x] ) {
int q = t[p][x];
if( len[q] == len[p]+1 ) return q;
else {
int nq = ++ind; len[nq] = len[p]+1;
memcpy(t[nq],t[q],sizeof t[q]), fa[nq] = fa[q], fa[q] = nq;
for(; p && t[p][x] == q; p = fa[p]) t[p][x] = nq;
return nq;
}
}
int np = ++ind; len[np] = len[p]+1;
for(; p && !t[p][x]; p = fa[p]) t[p][x] = np;
if( !p ) fa[np] = 1;
else {
int q = t[p][x];
if( len[q] == len[p]+1 ) fa[np] = q;
else {
int nq = ++ind; len[nq] = len[p]+1;
memcpy(t[nq],t[q],sizeof t[q]), fa[nq] = fa[q], fa[q] = fa[np] = nq;
for(; p && t[p][x] == q; p = fa[p]) t[p][x] = nq;
}
}
return np;
}
} ;
- 后缀平衡树
#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
#define mm (ll+rr)/2
const double X = 1e15;
int n,rt,ind,ver[N];
char s[N]; string ss;
struct Node { int ch[2],siz; double val; } t[N];
void up(int u) { t[u].siz = t[ls(u)].siz + 1 + t[rs(u)].siz; }
void pia(int u) { if( ls(u) ) pia(ls(u)); ver[++ind] = u; if( rs(u) ) pia(rs(u)); }
void bld(int &u,int l,int r,double ll,double rr) {
if( l > r ) return u = 0, void();
int mid = l+r>>1;
u = ver[mid], t[u].val = mm;
bld(ls(u),l,mid-1,ll,mm), bld(rs(u),mid+1,r,mm,rr), up(u);
}
void ckbal(int &u,double ll,double rr) {
if( t[u].siz*0.75 < max(t[ls(u)].siz,t[rs(u)].siz) )
ind = 0, pia(u), bld(u,1,ind,ll,rr);
}
bool cmp(int x,int y) { return s[x]!=s[y] ? s[x]<s[y] : t[x-1].val<t[y-1].val; }
void ins(int &u,double ll=0,double rr=X) {
if( !u ) return t[u=n] = Node{0,0,1,mm}, void();
cmp(n,u) ? ins(ls(u),ll,t[u].val) : ins(rs(u),t[u].val,rr);
up(u), ckbal(u,ll,rr);
}
void ers(int &u) {
if( u == n ) {
if( !ls(u) || !rs(u) ) return u = ls(u) | rs(u), void();
int x = ls(u), fa = u;
if( !rs(x) ) rs(x) = rs(u);
else {
while( rs(x) ) --t[x].siz, x = rs(fa=x);
rs(fa) = ls(x), ls(x) = ls(u), rs(x) = rs(u);
}
return up(u=x);
}
ers(cmp(n,u)?ls(u):rs(u)), up(u);
}
int rk(int u) {
auto cmp=[=]() {
for(int i = 0, j = u; i < sz(ss); ++i, j -= !!j)
if( ss[i] < s[j] ) return 1;
else if( ss[i] > s[j] ) return 0;
return 0;
};
if( !u ) return 0;
return cmp() ? rk(ls(u)) : t[ls(u)].siz+1+rk(rs(u));
}
void push(char x) { s[++n] = x, ins(rt); } // 末尾插入
void pop() { ers(rt), --n; } // 末尾删除
int qry() { // 查询 ss 的出现次数
reverse(all(ss));
int res = rk(rt);
--ss.back();
return res - rk(rt);
}
回文串
- manacher
rFor(i,n,1) s[i*2] = s[i], s[i*2-1] = '#'; s[0] = s[n=2*n+1] = '#';
For(i,1,n, mid = 0, r = 0) {
if( i <= r ) f[i] = min(f[2*mid-i],r-i);
while( s[i-f[i]-1] == s[i+f[i]+1] ) ++f[i];
if( i+f[i] > r ) mid = i, r = i+f[i];
}
- PAM
字符集 \(a\sim z\)
struct {
int n,ind,s[N],lst,t[N][26],fail[N],len[N];
void init() { fail[0] = ind = 1, len[1] = s[0] = -1; }
int getfail(int u)
{ while( s[n] != s[n-len[u]-1] ) u = fail[u]; return u; }
void extend(int x) {
x -= 'a', s[++n] = x;
int u = getfail(lst);
if( !t[u][x] ) {
int v = ++ind;
fail[v] = t[getfail(fail[u])][x], t[u][x] = v;
len[v] = len[u]+2;
}
lst = t[u][x];
}
} ;