首页 > 其他分享 >【模板】字符串

【模板】字符串

时间:2024-07-13 22:52:47浏览次数:18  
标签:fa int ++ len ind 字符串 nq 模板

字符串

  • 哈希

素数:131 1061 2e6+93 1e7+19 2e7+93 3e7+23 1e9+97 LL(1e16)+61

  • Z function
n = strlen(s+1), m = strlen(t+1);
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( s[z[i]+1] == s[i+z[i]] ) ++z[i];
	if( i+z[i]-1 > r ) l = i, r = i+z[i]-1;
}
For(i,1,m, l = 0, r = 0) {
	int len = 0;
	if( i <= r ) len = min(z[i-l+1],r-i+1);
	while( i+len <= m && s[len+1] == t[i+len] ) ++len;
	if( i+len-1 > r ) l = i, r = i+len-1;
}
  • 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];
	}
} ;

标签:fa,int,++,len,ind,字符串,nq,模板
From: https://www.cnblogs.com/ft61/p/18300882

相关文章

  • 24暑假算法刷题 | Day9 | LeetCode 151. 反转字符串中的单词,28. 找出字符串中第一个匹
    目录151.反转字符串中的单词题目描述题解28.找出字符串中第一个匹配项的下标题目描述题解459.重复的子字符串题目描述题解卡码网55.右旋字符串题目描述题解151.反转字符串中的单词点此跳转题目链接题目描述给你一个字符串s,请你反转字符串中单词的顺......
  • 欧拉函数(模板)
    873.欧拉函数-AcWing题库874.筛法求欧拉函数-AcWing题库#include<bits/stdc++.h>usingnamespacestd;intget_erlers(intx){intres=x;for(inti=2;i<=x/i;i++){if(x%i==0){res=res/i*(i-1);while(x%i......
  • 约数问题(模板)
    869.试除法求约数-AcWing题库#include<bits/stdc++.h>usingnamespacestd;vector<int>solve(intx){vector<int>ans;for(inti=1;i<=x/i;i++){if(x%i==0){ans.push_back(i);if(x/i!=i)a......
  • [Redis]字符串详解
    Redis中的字符串是可以修改的字符串,在内存中它是以字节数组的形式存在的。我们知道C语言里面的字符串标准形式是以NULL(即0x\0)作为结束符,但是在Redis里面,字符串不是这么表示的。因为要获取以NULL结尾的字符串的长度使用的是strlen标准库函数,这个函数的算法复杂度是0(n......
  • Js 前置,后置补零的原生方法与补字符串 padStart及padEnd
    在工作中,遇到了需要将不满八位的一个字符串进行后补0的操作,所以就在网上学习了关于js原生补充字符串的方法,然后用这篇博客记录下来。目录前置补充字符串 String.prototype.padStart()后置补充字符串String.prototype.padEnd()前置补充字符串 String.prototype.padStart......
  • Linux 中 grep命令仅仅输出匹配的字符串
     001、[root@PC1test]#lsa.txt[root@PC1test]#cata.txt##测试数据aa33aa77bbaaaa22aakkccbbddaauu883388rrqq[root@PC1test]#grep-oP"aa"a.txt##输出仅仅匹配的内容,但是换行了aaaaaaaaaaaa[root@PC1test]......
  • ssycms模板文件结构
    模板文件结构资源目录结构├─tempalte模板文件夹  ├─default  模板名称  │├─css  CSS静态资源目录  │  ├─html  HTML模板目录  │  ├─images图片资源目录  │  ├─jsJavaScript资源目录  │  └─template.json模板配......
  • ssycms 详情模板页
    详情模板页以下列出常用详情模板页面调用标签代码你也可以将本篇内容复制到详情模板页中查看 template\default\html\article\articleDetail.html常用文章信息调用标签(仅在详情页面起作用)文章标题:{$itemInfo['title']}文章地址:{$itemInfo['url']}文章关键词:{$itemInfo['ke......
  • C++数组 字符串
    是什么:相同类型元素的集合写法:intexample[3]//数组在声明大小时必须为常数数组名example是个指针类型如int*ptr=example;数组索引的工作原理:example[3]//从首地址位置偏移数组类型大小(int是4字节)乘索引值(4*3)个字节//从当前字节位置往后读四个字节;可能出现的错误:ex......
  • 后缀数组【jiangly模板】
    目录后缀数组简介后缀数组可以用于什么场景如何实现后缀数组倍增法求后缀数组\(height\)数组\(LCP\)(最长公共前缀)\(height\)代码模板参考文章后缀数组是一种非常强大的一种处理字符串问题的工具后缀数组简介前置知识:计数排序、基数排序后缀数组(SuffixArray)主要关系到两......