【模板】字符串

字符串

  • 哈希

素数: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];
	}
} ;
posted @ 2024-07-13 22:47  ft61  阅读(13)  评论(0编辑  收藏  举报