每日一题 2019/4/8

 

今天就整理模板吧

感谢牛逼网友的帮助,有了这些模板整理工具:

https://github.com/4thcalabash/code_library
http://www.planetb.ca/syntax-highlight-word
https://www.cnblogs.com/palayutm/p/6444833.html#e5898de8a880_2
https://github.com/wx-csy/code_library

先把所有的需要的东西放到这,然后再整理、打印

Vim配置:

windows:

syntax on
set backspace=indent,eol,start
set nu si ci ai mouse=a sw=4 sts=4 ts=4
set hlsearch incsearch
colorscheme desert
set guifont=Consolas:h12
set report=0 showmatch cursorline
set guioptions-=m
set guioptions-=T
nmap ggvG
vmap "*y
nmap : vs %<.in 
nmap : vs %<.out 
nmap : !%< 
nmap : !%< < %<.in 
nmap : !g++ % -o %< -std=c++11 
:cd D:\cpp

 ubantu:

set nu ai ci si sts=4 ts=4 sw=4 mouse=a 
nmap : vs %<.in 
nmap : !clear && time ./%< < %<.in  
nmap : vs %<.out 

nmap : !clear && g++ -std=c++11 % -o %< 
nmap : !clear && time ./%< 

nmap ggvG$
vmap "+y
nmap "+gp
imap "+pa

头文件、预操作:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl "\n"
#define fi first
#define se second
#define db double
#define gcd __gcd
#define pb push_back
#define mp make_pair
#define lowbit(x) x & (-x)
#define PII  pair 
#define all(x) x.begin(), x.end()
#define rep(i, a, b) for(__typeof(b) i = a; i <= (b); i++)
#define Rep(i, a, b) for(__typeof(a) i = a; i >= (b); i--)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const db eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
using __gnu_cxx::crope;
 
int main()
{
	return 0;
}

快速读入、输出:

inline int read(){
	char ch = getchar();
	int x = 0, f = 1;
	while(ch < '0' || ch > '9'){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
 
inline void write(int x){
	if (x < 0) x = ~x + 1, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

LCS:


char s[maxn], t[maxn];
int dp[maxn][maxn];

int n = strlen(s + 1), m = strlen(t + 1);
rep(i, 1, n){
	rep(j, 1, m){
		if(s[i] == t[j]) dp[i][j] = dp[i-1][j-1] + 1;
		else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
	}
}
printf("%d\n", dp[n][m]);

LIS:


fill(dp, dp + n + 1, inf);
rep(i, 1, n){
	*lower_bound(dp + 1, dp + n + 1, a[i]) = a[i];
}
printf("%d\n", lower_bound(dp + 1, dp + n + 1, inf) - dp - 1);

 Bellman_Ford:


struct edge{
	int from, to, cost;
}e[maxn];
 
int d[maxn];

bool Bellman_Frod(int s){
	memset(d, 0, sizeof(d));
	rep(i, 1, n){
		rep(j, 1, m){
			edge t = e[j];
			if(d[t.to] > d[t.from] + t.cost){
				d[t.to] = d[t.from] + t.cost;
				if(i == n) return true;
			}
		}
	}
	return false;
}

Dijkstra+heap:


struct edge{
	int to, cost;
	edge(){}
	edge(int to, int cost){
		this->to = to, this->cost = cost;
	}
};
 
vector G[maxn];
int d[maxn];
int n, m;
 
void dij(int s){
	priority_queue, greater > q;
	fill(d, d + n + 1, inf);
	d[s] = 0;
	q.push(PII(0, s));
	while(!q.empty()){
		PII p = q.top(); q.pop();
		int v = p.se;
		if(d[v] < p.fi) continue;
		int len = G[v].size();
		rep(i, 0, len - 1){
			edge e = G[v][i];
			if(d[e.to] > d[v] + e.cost){
				d[e.to] = d[v] + e.cost;
				q.push(PII(d[e.to], e.to));
			}
		}
	}
}

MST:

struct edge{
	int u, v, cost;
	friend bool operator < (edge a, edge b){
		return a.cost < b.cost;
	}
};
 
edge es[maxm];
int fa[maxn];
int n, m;
 
int Find(int x){ return fa[x] == x ? x : fa[x] = Find(fa[x]); }
void uni(int x, int y){ fa[Find(x)] = Find(y); }
void init(){ rep(i, 0, n + 1) fa[i] = i; }
 
int solve(){
	init();
	sort(es + 1, es + m + 1);
	int res = 0;
	rep(i, 1, m){
		edge e = es[i];
		if(Find(e.u) != Find(e.v)){
			uni(e.u, e.v);
			res += e.cost;
		}
	}
	return res;
}

次小生成树:

#define int ll
 
struct edge{
	int from, to, val;
	friend bool operator <(edge a, edge b){
		return a.val < b.val;
	}
}es[maxn];
 
vector G[maxn];
bool vis[maxn];
int fa[maxn], dep[maxn], acst[maxn][22];
int Max1[maxn][22], Max2[maxn][22];
int lg[maxn];
int n, m; 
 
int Find(int x) { return fa[x] == x ? x : fa[x] = Find(fa[x]); }
void uni(int x, int y) { fa[Find(x)] = Find(y); }
 
void init() {
	//memset(dep, 0, sizeof(dep));
	//memset(acst, 0, sizeof(acst));
	//memset(Max1, 0, sizeof(Max1));
	//memset(Max2, 0, sizeof(Max2));
	//rep(i, 0, n) vis[i] = 0;
	rep(i, 0, n) fa[i] = i; 
	//rep(i, 0, n) G[i].clear();
	rep(i, 1, n){
		lg[i] = lg[i-1] + ((1 << lg[i-1]) == i);
	}
}
 
void dfs(int x){
	int len = G[x].size();
	rep(i, 0, len - 1){
		int y = G[x][i];
		int nxt = es[y].from == x ? es[y].to : es[y].from;
		int val = es[y].val;
		if(acst[x][0] == nxt) continue;
		acst[nxt][0] = x, Max1[nxt][0] = val;
		dep[nxt] = dep[x] + 1;
		dfs(nxt);
	}
}
 
void work(){
	rep(j, 1, 19){
		rep(i, 1, n){
			acst[i][j] = acst[acst[i][j-1]][j-1];
			Max1[i][j] = max(Max1[i][j-1], Max1[acst[i][j-1]][j-1]);
			Max2[i][j] = max(Max2[i][j-1], Max2[acst[i][j-1]][j-1]);
			if(Max1[i][j-1] != Max1[acst[i][j-1]][j-1]) Max2[i][j] = max(Max2[i][j], min(Max1[i][j-1], Max1[acst[i][j-1]][j-1]));
		}
	}
}
 
int MAX(int x, int a, int b, int val)
{
	if(val > Max1[a][b]) return max(x, Max1[a][b]);
	return max(x, Max2[a][b]);
}
 
int Get(int x, int y, int val){
	if(dep[x] < dep[y]) swap(x, y);
	int i, res = 0;
	while(dep[x] > dep[y]) {
		i = lg[dep[x]-dep[y]] - 1;
		res = MAX(res, x, i, val);
		x = acst[x][i];
	}
	if(x == y) return res;
	i = 0;
	while(acst[x][i] != acst[y][i]) i++;
	for( ; i >= 0; i--){
		if(acst[x][i] != acst[y][i]) {
			res = MAX(MAX(res, x, i, val), y, i, val);
			x = acst[x][i], y = acst[y][i];
		}
	}
	return MAX(MAX(res, x, 0, val), y, 0, val); 
}
 
int32_t main()
{
	scanf("%lld %lld", &n, &m);
	init();
	rep(i, 1, m){
		scanf("%lld %lld %lld", &es[i].from, &es[i].to, &es[i].val);
	}
	sort(es + 1, es + m + 1);
	int res = 0, cnt = 0;
	rep(i, 1, m){
		if(cnt >= n) break;
		int fu = Find(es[i].from), fv = Find(es[i].to);
		if(fu != fv){
			vis[i] = 1;
			uni(fu, fv);
			res += es[i].val;
			cnt++;
			G[es[i].from].pb(i);
			G[es[i].to].pb(i);
		}
	}
	dep[1] = 1, dfs(1);
	work();
	int ans = INF, t;
	rep(i, 1, m){
		if(!vis[i]){
			t = Get(es[i].from, es[i].to, es[i].val);
			ans = min(ans, res + es[i].val - t);
		}
	}
	printf("%lld\n", ans);
	return 0;
}

树状数组:

int c[maxn];
 
int getsum(int x){
	int ret = 0;
	for( ; x > 0; ret += c[x], x -= lowbit(x));
	return ret;
}
 
void update(int x, int val){
	for ( ; x <= maxn; c[x] += val, x += lowbit(x));
}

最大流:

FF:

struct edge{
	int to, cap, rev;
};
 
vector G[maxn];
bool vis[maxn];
 
void add_edge(int from, int to, int cap){
	G[from].pb((edge){to, cap, G[to].size()});
	G[to].pb((edge){from, 0, G[from].size() - 1});
}
 
int dfs(int v, int t, int f){
	if(v == t) return f;
	vis[v] = 1;
	rep(i, 0, G[v].size() - 1){
		edge &e = G[v][i];
		if(!vis[e.to] && e.cap > 0){
			int d = dfs(e.to, t, min(f, e.cap));
			if(d > 0){
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
 
int max_flow(int s, int t){
	int flow = 0;
	for( ; ; ){
		memset(vis, 0, sizeof(vis));
		int f = dfs(s, t, inf);
		if(f == 0) return flow;
		flow += f;
	}
}

Dinic:

int n, m, k, cnt;
struct node{
	int next = -1;
	int to;
	int w;
};

int head[maxn], dep[maxn];
int d[805][805], pos[maxn];
node edge[maxn];

void init(){
	cnt = -1;
	memset(head, -1, sizeof(head));
}

void add_edge(int x, int y, int z){
	cnt++;
	edge[cnt].to = y;
	edge[cnt].next = head[x];
	edge[cnt].w = z;
	head[x] = cnt;
}
//x->y一条容量为z的边做法:
//add_edge(x, y, z), add_edge(y, x, 0)

int bfs(){
	memset(dep, 0, sizeof(dep));
	queue q;
	while(!q.empty()) q.pop();
	dep[s] = 1;
	q.push(s);
	do{
		int u = q.front();
		q.pop();
		for(int i = head[u]; i != -1; i = edge[i].next){
			if(edge[i].w > 0 && dep[edge[i].to] == 0){
				dep[edge[i].to] = dep[u] + 1;
				q.push(edge[i].to);
			}
		}
	}while(!q.empty());
	return dep[t] != 0;
}
int dfs(int u, int dist){
	if(u == t) return dist;
	for(int i = head[u]; i != -1; i = edge[i].next){
		if((dep[edge[i].to] == dep[u] + 1) && (edge[i].w != 0)){
			int di = dfs(edge[i].to, min(dist, edge[i].w)); 
			if(di > 0){
				edge[i].w -= di;
				edge[i^1].w += di;
				return di;
			}
		}
	}
	return 0;
}

int dinic()
{
	int ans = 0;
	while(bfs()) while(int di = dfs(s, inf)) ans += di;
	return ans;
}

计算几何:(有待完善) 

inline int sign(db a) { return a < -eps ? -1 : a > eps; }//判断符号
inline bool dcmp(db x, db y){ return fabs(x - y) < eps ? 1 : 0; }
inline db add(db a, db b){ return fabs(a + b) < eps * (fabs(a) + fabs(b)) ? 0 : a + b; }
inline int cmp(db a, db b) { return sign(a - b); }
 
struct P{
	db x, y;
	P() {} 
	P(db x, db y) : x(x), y(y) {}
	P operator + (P p) { return P(add(x, p.x), add(y, p.y)); }
	P operator - (P p) { return P(add(x, -p.x), add(y, -p.y)); }
	P operator * (db d) { return P(x * d, y * d); }
	P operator / (db d) { return P(x / d, y / d); }
	bool operator == (P p) { return dcmp(p.x, x) && dcmp(p.y, y); }
	bool operator != (P p) { return !dcmp(p.x, x) || !dcmp(p.y, y); }
	bool operator < (P p) const{//具体而定
		if(dcmp(x, p.x)) return y < p.y;
		return x < p.x;
	}
	db dot(P p) { return x * p.x + y * p.y; }
	db det(P p) { return x * p.y - y * p.x; }
	db abs() { return sqrt(x * x + y * y); }
	db abs2() { return x * x + y * y; }
	db getw() { return atan2(y, x); }
};
 
db Length(P a) { return sqrt(a.dot(a)); }//模
db angle(P p1, P p2){ return atan2l(p1.det(p2), p1.dot(p2)); }//夹角的弧度值
db cross(P p1, P p2, P p3) { return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y); }
int crossOp(P p1, P p2, P p3) { return sign(cross(p1, p2, p3)); }
 
bool chkLL(P p1, P p2, P q1, P q2){//直线平行
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return !sign(a1 + a2);
}
 
P proj(P p1, P p2, P q){//q到直线p1-p2的投影点
	P dir = p2 - p1;
	return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
 
bool intersect(db l1, db r1, db l2, db r2){//为后面用
	if(l1 > r1) swap(l1, r1);
	if(l2 > r2) swap(l2, r2);
	return !(cmp(r1, l2) == -1 || cmp(r2, l1) == -1);
}
 
bool isSS(P p1, P p2, P q1, P q2){//线段相交
	return intersect(p1.x, p2.x, q1.x, q2.x) && intersect(p1.y, p2.y, q1.y, q2.y) && 
		crossOp(p1, p2, q1) * crossOp(p1, p2, q2) <= 0 && 
		crossOp(q1, q2, p1) * crossOp(q1, q2, p2) <= 0;
}
 
bool isSS_strict(P p1, P p2, P q1, P q2){//严格相交
	return  crossOp(p1, p2, q1) * crossOp(p1, p2, q2) <= 0 && 
		crossOp(q1, q2, p1) * crossOp(q1, q2, p2) <= 0;
}
 
bool isMiddle(db a, db m, db b){
	return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
 
bool isMiddle(P a, P m, P b){
	return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
 
bool on_seg(P p1, P p2, P q){//判断点q在线段p1-p2上
	return crossOp(p1, p2, q) == 0 && isMiddle(p1, q, p2);
}
 
bool on_seg_strict(P p1, P p2, P q){
	return crossOp(p1, p2, q) == 0 && sign((q - p1).dot(p1 - p2)) * sign((q - p2).dot(p1 - p2)) < 0;
}
 
P getLL(P p1, P p2, P q1, P q2){//直线p1-p2, q1-q2的交点
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}

矩阵快速幂:


struct Matrix
{
	int mat[maxn][maxn];
	Matrix() {}
	Matrix operator*(Matrix const &b)const
	{
		Matrix res;
		memset(res.mat, 0, sizeof(res.mat));
		for (int i = 0 ;i < maxn; i++)
			for (int j = 0; j < maxn; j++)
				for (int k = 0; k < maxn; k++)
					res.mat[i][j] = (res.mat[i][j]+this->mat[i][k] * b.mat[k][j])%mod;
		return res;
	}
};
 
Matrix pow_mod(Matrix base, int n)
{
	Matrix res;
	memset(res.mat, 0, sizeof(res.mat));
	for (int i = 0; i < maxn; i++)
		res.mat[i][i] = 1;
	while (n > 0)
	{
		if (n & 1) res = res*base;
		base = base*base;
		n >>= 1;
	}
	return res;
}
 
int main()
{
	Matrix base;
	for(int i = 0; i < maxn; i++){
		for(int j = 0; j < maxn; j++){
			base.mat[i][j] = 1;
		}
	}
	base.mat[1][1] = 0;
	int n;
	while(~scanf("%d", &n) && (n + 1)){
		Matrix ans = pow_mod(base, n);
		printf("%d\n", ans.mat[0][1]);
	}
	return 0;
}

倍增LCA:


vector G[maxn];
bool vis[maxn];
int lg[maxn], dep[maxn];
int acst[maxn][22];
int n;
 
void dfs(int u, int fa){
	int len = G[u].size();
	acst[u][0] = fa;
	for(int i = 1; (1 << i) <= dep[u]; i++){
		acst[u][i] = acst[acst[u][i-1]][i-1];
	}
	rep(i, 0, len - 1){
		int v = G[u][i];
		if(v != fa){
			dep[v] = dep[u] + 1;
			dfs(v, u);
		}
	}
}
 
int LCA(int x, int y){
	if(dep[x] < dep[y]) swap(x, y);
	while(dep[x] > dep[y]) {
		x = acst[x][lg[dep[x]-dep[y]]-1];
	}
	if(x == y) return x;
	Rep(k, lg[dep[x]] - 1, 0){
		if(acst[x][k] != acst[y][k]) x = acst[x][k], y = acst[y][k];
	}
	return acst[x][0];
}
 
void init(){
	rep(i, 1, n){
		lg[i] = lg[i-1] + ((1 << lg[i-1]) == i);
	}
}

Manacher:

char Ma[maxn*2];
int p[maxn*2];
void Manacher(char s[], int len){
	int l = 0;
	Ma[l++] = '$';
	Ma[l++] = '#';
	rep(i, 0, len - 1){
		Ma[l++] = s[i];
		Ma[l++] = '#';
	}
	Ma[l] = 0;
	int mx = 0, id = 0;
	rep(i, 0, l - 1){
		p[i] = mx > i ? min(p[2*id-i], mx - i) : 1;
		while(Ma[i+p[i]] == Ma[i-p[i]]) p[i]++;
		if(i + p[i] > mx){
			mx = i + p[i];
		}
		id = i;
	}
}

char s[maxn];
int main()
{
	scanf("%s", s);
	int len = strlen(s);
	Manacher(s, len);
	int ans = 0;
	rep(i, 0, 2 * len + 1) ans = max(ans, p[i] - 1);
	return 0;
}

最大权闭合子图:

//首先建模,一个超级源点和一个超级汇点,源点和正权点连边,汇点和负权点连边,权值就是点值,图中的所有关系边边权为inf,结论就是最大权闭合子图的权值为 所有正点权之和减去最小割的权值和

//然后跑最大流就是答案

计算组合数:

费马小定理:

ll fac[maxn];  
 
ll qpow(ll x, ll y){
	ll res = 1;
	while(y){
		if(y & 1) res = (res * x) % mod;
		y >>= 1;
		x = (x * x) % mod;
	}
	return res;
}
 
void init(){
	fac[0] = 1;
	for(int i = 1; i < maxn; i++){
		fac[i] = fac[i-1] * i % mod;
	}
}
 
ll Com(ll n,ll m){  
	init();
	if(m > n || m < 0) return 0;  
	ll a = fac[n], b = fac[n-m] * fac[m] % mod;  
	return a * qpow(b, mod - 2) % mod;
}  

打表:

ll C[maxn][maxn];
 
void init(){
	rep(i, 0, 5000){
		rep(j, 0, i){
			C[i][j] = 1;
		}
	}
	rep(i, 2, 5000){
		rep(j, 1, i){
			C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
		}
	}
}

字符串最小表示:

int n = strlen(s + 1);
rep(i, 1, n) s[n+i] = s[i];
int i = 1, j = 2, k;
while(i <= n && j <= n){
	for(k = 0; k < n && s[i+k] == s[j+k]; k++);
	if(k == n) break;
	if(s[i+k] > s[j+k]){
		i = i + k + 1;
		if(i == j) i++;
	} else {
		j = j + k + 1;
		if(i == j) j++;
	}
}
int ans = min(i, j);

主席树:

int a[maxn], b[maxn];
int L[20*maxn], R[20*maxn];
int T[maxn], sum[20*maxn];
int n, m, q, tot = 0;
 
inline int build(int l, int r){
	int rt = ++tot;
	if(l < r){
		int mid = (l + r) >> 1;
		L[rt] = build(l, mid);
		R[rt] = build(mid + 1, r);
	}
	return rt;
}
 
inline int update(int pre, int l, int r, int x){
	int rt = ++tot;
	L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre] + 1; 
	if(l < r){
		int mid = (l + r) >> 1;
		if(x <= mid) L[rt] = update(L[pre], l, mid, x);
		else R[rt] = update(R[pre], mid + 1, r, x);
	}
	return rt;
}
 
inline int query(int u, int v, int l, int r, int k){
	if(l == r) return l;
	int x = sum[L[v]] - sum[L[u]], mid = (l + r) >> 1;
	if(x >= k) return query(L[u], L[v], l, mid, k);
	else return query(R[u], R[v], mid + 1, r, k - x);
}
 
int main()
{
	int t; scanf("%d", &t);
	while(t--){
		tot = 0;
		scanf("%d %d", &n, &q);
		rep(i, 1, n) scanf("%d", a + i), b[i] = a[i];
		sort(b + 1, b + n + 1);
		m = unique(b + 1, b + n + 1) - b - 1;
		T[0] = build(1, m);
		rep(i, 1, n){
			a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b;
			T[i] = update(T[i-1], 1, m, a[i]);
		}
		while(q--){
			int l, r, k; scanf("%d %d %d", &l, &r, &k);
			int p = query(T[l-1], T[r], 1, m, k);
			printf("%d\n", b[p]);
		}
	}
	return 0;
}

KMP:

//主串a, 模式串b, 输出所有出现的位置以及nxt数组
char a[maxn], b[maxn];
int nxt[maxn];

int main()
{
	scanf("%s %s", a + 1, b + 1);
	int la = strlen(a + 1), lb = strlen(b + 1);
	int j = 0;
	rep(i, 2, lb){
		while(j && b[i] != b[j+1]) j = nxt[j];    
		if(b[j+1] == b[i])j++;    
		nxt[i] = j;
	}
	j = 0;
	rep(i, 1, la){
		while(j > 0 && b[j+1] != a[i]) j = nxt[j];
		if(b[j+1] == a[i]) j++;
		if(j == lb) printf("%d\n", i - lb + 1), j = nxt[j];
	}
	rep(i, 1, lb) printf("%d ", nxt[i]);
	return 0;
}

AC自动机:

//n个模式串和一个主串,输出有多少模式串出现过
queue q;

struct Aho_Corasick_Automaton{
	int c[maxn][26], val[maxn], fail[maxn], cnt;
	void ins(char *s){
		int len = strlen(s), now = 0;
		rep(i, 0, len - 1){
			int v = s[i] - 'a';
			if(!c[now][v]) c[now][v] = ++cnt;
			now = c[now][v];
		}
		val[now]++;
	}
	void build(){
		rep(i, 0, 25) if(c[0][i]) fail[c[0][i]] = 0, q.push(c[0][i]);
		while(!q.empty()){
			int u = q.front(); q.pop();
			rep(i, 0, 25) if(c[u][i]) fail[c[u][i]] = c[fail[u]][i], q.push(c[u][i]);
			else c[u][i] = c[fail[u]][i];
		}
	}
	int query(char *s){
		int len = strlen(s), now = 0, ans = 0;
		rep(i, 0, len - 1){
			now = c[now][s[i]-'a'];
			for(int t = now; t && ~val[t]; t = fail[t]) ans += val[t], val[t] = -1;
		}
		return ans;
	}
}AC;

char p[1000005];
int n;

int main()
{
	scanf("%d",&n);
	rep(i, 1, n) scanf("%s", p), AC.ins(p);
	AC.build();
	scanf("%s", p);int ans = AC.query(p);
	printf("%d\n", ans);
	return 0;
}

后缀数组:

//读入一个长度为n的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 1 到 n
char s[maxn];
int n, m, rak[maxn], sa[maxn], tax[maxn], tp[maxn];

void Qsort() {
	rep(i, 0, m) tax[i] = 0;
	rep(i, 1, n) tax[rak[i]]++;
	rep(i, 1, m) tax[i] += tax[i-1];
	Rep(i, n, 1) sa[tax[rak[tp[i]]]--] = tp[i];
}

void SuffixSort() {
	m = 75;
	rep(i, 1, n) rak[i] = s[i] - '0' + 1, tp[i] = i;
	Qsort();
	for(int w = 1, p = 0; p < n; m = p, w <<= 1) {
		//w:当前倍增的长度,w = x表示已经求出了长度为x的后缀的排名,现在要更新长度为2x的后缀的排名
		//p表示不同的后缀的个数,很显然原字符串的后缀都是不同的,因此p = n时可以退出循环
		p = 0;//这里的p仅仅是一个计数器000
		rep(i, 1, w) tp[++p] = n - w + i;
		rep(i, 1, n) if (sa[i] > w) tp[++p] = sa[i] - w; //这两句是后缀数组的核心部分,我已经画图说明
		Qsort();//此时我们已经更新出了第二关键字,利用上一轮的rak更新本轮的sa
		std::swap(tp, rak);//这里原本tp已经没有用了
		rak[sa[1]] = p = 1;
		rep(i, 2, n) rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++p;
		//这里当两个后缀上一轮排名相同时本轮也相同,至于为什么大家可以思考一下
	}
	rep(i, 1, n) printf("%d ", sa[i]); puts("");
}
int main()
{
	scanf("%s", s + 1);
	n = strlen(s + 1);
	SuffixSort();
	return 0;
}

字符串hash:

//求区间不相同子串个数
const int Hash = 10007;
const int maxn = 2100;

struct hashmap{
    int head[Hash],nxt[maxn],size;
    unsigned long long state[maxn];
    int f[maxn];
    void init(){
        size = 0;
        memset(head, -1, sizeof(head));
    }
    int insert(unsigned long long val,int id){
        int h = val % Hash;
        for(int i = head[h]; i != -1; i = nxt[i]){
            if(val == state[i]){
                int temp = f[i];
                f[i] = id;
                return temp;
            }
        }
        f[size] = id;
        state[size] = val;
        nxt[size] = head[h];
        head[h] = size++;
        return 0;
    }
} h;

const int seed = 13331;
unsigned long long P[maxn];
unsigned long long S[maxn];
char str[maxn];
int ans[maxn][maxn];

int main()
{
    P[0] = 1;
    rep(i, 1, maxn - 1) P[i] = P[i-1] * seed;
    int T; scanf("%d", &T);
    while(T--){
        scanf("%s", str);
        int n = strlen(str);
        rep(i, 1, n) S[i] = S[i-1] * seed + str[i-1];
        memset(ans, 0, sizeof(ans));
        rep(L, 1, n){
            h.init();
            rep(i, 1, n - L + 1){
                int l = h.insert(S[i+L-1] - S[i-1] * P[L], i);
                ans[i][i+L-1]++;
                ans[l][i+L-1]--;
            }
        }
        Rep(i, n, 0)
            rep(j, i, n)
                ans[i][j] += ans[i+1][j] + ans[i][j-1] - ans[i+1][j-1];
        int Q; scanf("%d",&Q);
        while(Q--){
            int a,b;
            scanf("%d%d", &a, &b);
            printf("%d\n", ans[a][b]);
        }
    }
    return 0;
}

 

你可能感兴趣的:(每日一题,ICPC竞赛模板)