模板库
yuanzhiteng · · 个人记录
用于考前练习板子。
零. 目录
已经完成了的:
- 图论
树的直径
树的重心
最近公共祖先
重链剖分
树上启发式合并
树哈希
最小生成树(
最短路(
差分约束系统
同余最短路(待补充)
失配树
一. 图论
树的直径
here
/*知识点:树的直径*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 1e4 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n;
int head[maxn],cnt;
struct Edge{
int to,next,w;
}e[maxn << 1];
inline void add(int u,int v,int w){
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
int deep[maxn];
int pos,pos1,pos2;
inline void dfs(int u,int fa){
if(deep[u] > deep[pos]) pos = u;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
deep[v] = deep[u] + e[i].w;
dfs(v,u);
}
}
int main(){
read(n);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v,1);
add(v,u,1);
}
dfs(1,0);
pos1 = pos;
deep[pos1] = 0;
pos = 0;
dfs(pos1,0);
pos2 = pos;
printf("%d\n",deep[pos2]);
return 0;
}
树的重心
here
/*知识点:树的重心*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 2e4 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int T;
int n;
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int dp[maxn],sz[maxn],root;
inline void dfs(int u,int fa){
sz[u] = 1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs(v,u);
sz[u] += sz[v];
dp[u] = max(dp[u],sz[v]);
}
dp[u] = max(dp[u],n - sz[u]);
if(dp[u] <= n / 2 && (!root || u < root))
root = u;
}
inline void init(){
cnt = root = 0;
for(int i=1;i<=n;i++) dp[i] = head[i] = 0;
}
int main(){
read(T);
while(T--){
read(n);
init();
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
dfs(1,0);
printf("%d %d\n",root,dp[root]);
}
return 0;
}
最近公共祖先 Lca
here
/*知识点:倍增lca*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 5e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,q,root;
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int fa[maxn][20],deep[maxn];
inline void dfs(int u,int Fa){
deep[u] = deep[Fa] + 1;
fa[u][0] = Fa;
for(int i=1;i<=18;i++)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == Fa) continue;
dfs(v,u);
}
}
inline int lca(int u,int v){
if(deep[u] < deep[v]) swap(u,v);
for(int i=18;i>=0;i--)
if(deep[fa[u][i]] >= deep[v])
u = fa[u][i];
if(u == v) return u;
for(int i=18;i>=0;i--)
if(fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int main(){
read(n,q,root);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
dfs(root,root);
while(q--){
int u,v;
read(u,v);
printf("%d\n",lca(u,v));
}
return 0;
}
/*知识点:Tarjan lca*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 5e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,q,root;
int head[maxn],cnt;
int qhead[maxn],qcnt;
struct Edge{
int to,next;
}e[maxn << 1],qe[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
inline void qadd(int u,int v){
qe[++qcnt].to = v;
qe[qcnt].next = qhead[u];
qhead[u] = qcnt;
}
int fa[maxn];
inline int find(int x){
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
int lca[maxn << 1];
bool vis[maxn];
inline void Tarjan(int u){
vis[u] = 1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(vis[v]) continue;
Tarjan(v);
fa[v] = u;
}
for(int i=qhead[u];i;i=qe[i].next){
int v = qe[i].to;
if(vis[v]){
lca[i] = find(v);
if(i & 1) lca[i + 1] = lca[i];
else lca[i - 1] = lca[i];
}
}
}
int main(){
read(n,q,root);
for(int i=1;i<=n;i++) fa[i] = i;
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
for(int i=1;i<=q;i++){
int u,v;
read(u,v);
qadd(u,v);
qadd(v,u);
}
Tarjan(root);
for(int i=1;i<=q;i++)
printf("%d\n",lca[i << 1]);
return 0;
}
/*知识点:树剖lca*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 5e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,q,root;
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int deep[maxn],sz[maxn],fa[maxn],Son[maxn];
inline void dfs1(int u,int fau){
fa[u] = fau;
sz[u] = 1;
deep[u] = deep[fau] + 1;
int son = -1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fau) continue;
dfs1(v,u);
sz[u] += sz[v];
if(sz[v] > son){
Son[u] = v;
son = sz[v];
}
}
}
int dfn[maxn],top[maxn];
int Time;
inline void dfs2(int u,int topu){
top[u] = topu;
dfn[u] = ++Time;
if(!Son[u]) return;
dfs2(Son[u],topu);
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa[u] || v == Son[u]) continue;
dfs2(v,v);
}
}
inline int lca(int u,int v){
while(top[u] != top[v]){
if(deep[top[u]] < deep[top[v]]) swap(u,v);
u = fa[top[u]];
}
if(deep[u] > deep[v]) swap(u,v);
return u;
}
int main(){
read(n,q,root);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
dfs1(root,root);
dfs2(root,root);
for(int i=1;i<=q;i++){
int u,v;
read(u,v);
printf("%d\n",lca(u,v));
}
return 0;
}
重链剖分
here
/*知识点:重链剖分*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,q,root;
ll mod;
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
inline void chadd(ll &x,ll y){
x = (x + y) % mod;
}
int Idfn[maxn];
ll a[maxn];
struct Segment_Tree{
struct Segment{
ll val,tag;
}tree[maxn << 2];
inline int left(int x){
return x << 1;
}
inline int right(int x){
return x << 1 | 1;
}
inline void push_up(int p){
tree[p].val = (tree[left(p)].val + tree[right(p)].val) % mod;
}
inline void get(int p,int l,int r,ll x){
chadd(tree[p].val,x * (r - l + 1ll));
chadd(tree[p].tag,x);
}
inline void push_down(int p,int l,int r){
if(!tree[p].tag) return;
int mid = (l + r) >> 1;
get(left(p),l,mid,tree[p].tag);
get(right(p),mid + 1,r,tree[p].tag);
tree[p].tag = 0;
}
inline void build(int p,int l,int r){
if(l == r){
tree[p].val = a[Idfn[l]] % mod;
return;
}
int mid = (l + r) >> 1;
build(left(p),l,mid);
build(right(p),mid + 1,r);
push_up(p);
}
inline void update(int p,int l,int r,int dl,int dr,ll x){
if(dl <= l && dr >= r){
chadd(tree[p].val,x * (r - l + 1ll));
chadd(tree[p].tag,x);
return;
}
push_down(p,l,r);
int mid = (l + r) >> 1;
if(dl <= mid) update(left(p),l,mid,dl,dr,x);
if(dr > mid) update(right(p),mid + 1,r,dl,dr,x);
push_up(p);
}
inline ll query(int p,int l,int r,int dl,int dr){
if(dl <= l && dr >= r) return tree[p].val;
push_down(p,l,r);
int mid = (l + r) >> 1;
ll ret = 0;
if(dl <= mid) ret = query(left(p),l,mid,dl,dr);
if(dr > mid) chadd(ret,query(right(p),mid + 1,r,dl,dr));
return ret;
}
}seg;
int sz[maxn],deep[maxn],fa[maxn],Son[maxn];
inline void dfs1(int u,int fau){
deep[u] = deep[fau] + 1;
sz[u] = 1;
fa[u] = fau;
int son = -1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fau) continue;
dfs1(v,u);
sz[u] += sz[v];
if(sz[v] > son){
Son[u] = v;
son = sz[v];
}
}
}
int dfn[maxn],top[maxn];
int Time;
inline void dfs2(int u,int topu){
top[u] = topu;
dfn[u] = ++Time;
Idfn[Time] = u;
if(!Son[u]) return;
dfs2(Son[u],topu);
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa[u] || v == Son[u]) continue;
dfs2(v,v);
}
}
inline void update(int u,int v,ll x){
while(top[u] != top[v]){
if(deep[top[u]] < deep[top[v]]) swap(u,v);
seg.update(1,1,n,dfn[top[u]],dfn[u],x);
u = fa[top[u]];
}
if(deep[u] < deep[v]) swap(u,v);
seg.update(1,1,n,dfn[v],dfn[u],x);
}
inline ll query(int u,int v){
ll ret = 0;
while(top[u] != top[v]){
if(deep[top[u]] < deep[top[v]]) swap(u,v);
chadd(ret,seg.query(1,1,n,dfn[top[u]],dfn[u]));
u = fa[top[u]];
}
if(deep[u] < deep[v]) swap(u,v);
chadd(ret,seg.query(1,1,n,dfn[v],dfn[u]));
return ret;
}
int main(){
read(n,q,root,mod);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
dfs1(root,root);
dfs2(root,root);
seg.build(1,1,n);
int op,u,v;
ll x;
while(q--){
read(op);
if(op == 1){
read(u,v,x);
update(u,v,x);
}
else if(op == 2){
read(u,v);
printf("%lld\n",query(u,v));
}
else if(op == 3){
read(u,x);
seg.update(1,1,n,dfn[u],dfn[u] + sz[u] - 1,x);
}
else{
read(u);
printf("%lld\n",seg.query(1,1,n,dfn[u],dfn[u] + sz[u] - 1));
}
}
return 0;
}
树上启发式合并 Dsu\ on\ tree
here
/*知识点:Dsu on tree*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 1e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,q;
int color[maxn];
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int sz[maxn],Son[maxn],dfn[maxn],point[maxn];
int Time;
inline void dfs1(int u,int fa){
sz[u] = 1;
dfn[u] = ++Time;
point[Time] = u;
int son = -1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs1(v,u);
sz[u] += sz[v];
if(sz[v] > son){
son = sz[v];
Son[u] = v;
}
}
}
int tot;
int ans[maxn],colorcnt[maxn];
inline void Add(int x){
if(!colorcnt[color[x]]) tot++;
colorcnt[color[x]]++;
}
inline void Delete(int x){
colorcnt[color[x]]--;
if(!colorcnt[color[x]]) tot--;
}
inline void dfs2(int u,int fa,bool type){
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa || v == Son[u]) continue;
dfs2(v,u,0);
}
if(Son[u]) dfs2(Son[u],u,1);
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa || v == Son[u]) continue;
for(int i=dfn[v];i<=dfn[v]+sz[v]-1;i++)
Add(point[i]);
}
Add(u);
ans[u] = tot;
if(!type)
for(int i=dfn[u];i<=dfn[u]+sz[u]-1;i++)
Delete(point[i]);
}
int main(){
read(n);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++) read(color[i]);
dfs1(1,1);
dfs2(1,1,1);
read(q);
while(q--){
int u;
read(u);
printf("%d\n",ans[u]);
}
return 0;
}
树哈希
here
/*知识点:树哈希*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <random>
#include <chrono>
#include <map>
using namespace std;
typedef unsigned long long ull;
const int maxn = 55;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,m;
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int dp[maxn],sz[maxn],root[maxn][2];
inline void dfs(int u,int fa,int id){
sz[u] = 1;
dp[u] = 0;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs(v,u,id);
sz[u] += sz[v];
dp[u] = max(dp[u],sz[v]);
}
dp[u] = max(dp[u],n - sz[u]);
if(dp[u] <= n / 2){
if(!root[id][0]) root[id][0] = u;
else root[id][1] = u;
}
}
ull Hash[maxn][maxn];
ull RealHash[maxn];
const ull mask = chrono::steady_clock::now().time_since_epoch().count();
inline ull XOR_SHIFT(ull x){
x ^= mask;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
x ^= mask;
return x;
}
inline void getHash(int u,int fa,int id){
Hash[id][u] = 1;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
getHash(v,u,id);
Hash[id][u] += XOR_SHIFT(Hash[id][v]);
}
}
map<ull,int>vis;
inline void init(){
cnt = 0;
memset(head,0,sizeof(head));
}
int main(){
read(m);
for(int i=1;i<=m;i++){
init();
read(n);
for(int j=1;j<=n;j++){
int v;
read(v);
if(!v) continue;
add(j,v);
add(v,j);
}
dfs(1,1,i);
getHash(root[i][0],root[i][0],i);
RealHash[i] = Hash[i][root[i][0]];
if(root[i][1]){
getHash(root[i][1],root[i][1],i);
RealHash[i] = min(RealHash[i],Hash[i][root[i][1]]);
}
}
for(int i=1;i<=m;i++){
if(!vis[RealHash[i]]){
vis[RealHash[i]] = i;
printf("%d\n",i);
}
else
printf("%d\n",vis[RealHash[i]]);
}
return 0;
}
最小生成树
/*知识点:kruskal最小生成树*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 2e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,m;
struct Edge{
int u,v,w;
}e[maxn];
int fa[maxn];
inline int find(int x){
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
inline bool cmp(Edge x,Edge y){
return x.w < y.w;
}
inline int kruskal(){
sort(e + 1,e + 1 + m,cmp);
int ret = 0,cnt = 0;
for(int i=1;i<=m;i++){
int u =e[i].u,v = e[i].v;
int rootu = find(u),rootv = find(v);
if(rootu == rootv) continue;
ret += e[i].w;
cnt++;
fa[rootu] = rootv;
}
if(cnt != n - 1){
printf("orz\n");
exit(0);
}
return ret;
}
int main(){
read(n,m);
for(int i=1;i<=n;i++) fa[i] = i;
for(int i=1;i<=m;i++) read(e[i].u,e[i].v,e[i].w);
printf("%d\n",kruskal());
return 0;
}
/*知识点:Prim最小生成树*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
const int maxn = 2e5 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int n,m;
int head[maxn],cnt;
struct Edge{
int to,next,w;
}e[maxn << 1];
inline void add(int u,int v,int w){
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
const int inf = 0x3f3f3f3f;
int dis[maxn];
struct node{
int pos,dis;
bool operator < (const node &x)const{
return x.dis < dis;
}
};
priority_queue<node>q;
bool vis[maxn];
inline void prim(){
for(int i=1;i<=n;i++) dis[i] = inf;
dis[1] = 0;
int edgecnt = 0,ret = 0;
q.push((node){1,0});
while(!q.empty() && edgecnt < n){ //注意一来就加了一条隐形的0边
int u = q.top().pos,w = q.top().dis;
q.pop();
if(vis[u]) continue;
vis[u] = 1;
ret += w;
edgecnt++;
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(e[i].w < dis[v])
dis[v] = e[i].w,q.push((node){v,dis[v]});
}
}
if(edgecnt == n) printf("%d\n",ret); //注意一来就加了一条隐形的0边
else printf("orz\n");
}
int main(){
read(n,m);
for(int i=1;i<=m;i++){
int u,v,w;
read(u,v,w);
add(u,v,w);
add(v,u,w);
}
prim();
return 0;
}
还有
最短路
here
/*知识点:Manacher*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 22000005;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int r[maxn],len;
int s[maxn];
inline void Manacher(char *c){
len = strlen(c + 1);
for(int i=1;i<=len;i++){
s[i << 1] = c[i];
s[(i << 1) - 1] = '#';
}
len = len << 1 | 1;
s[len] = '#';
int R = 0,pos = 0,pre = 0;
for(int i=1;i<=len;i++){
if(i > R){
while(i + r[i] <= len && i - r[i] >= 1 && s[i + r[i]] == s[i - r[i]]) r[i]++;
r[i]--;
if(i + r[i] > R) R = i + r[i],pos = i;
}
else{
pre = (pos << 1) - i;
if(pre - r[pre] > pos - r[pos]) r[i] = r[pre];
else if(pre - r[pre] < pos - r[pos]) r[i] = pos + r[pos] - i;
else{
r[i] = pos + r[pos] - i;
while(i + r[i] <= len && i - r[i] >= 1 && s[i + r[i]] == s[i - r[i]]) r[i]++;
r[i]--;
}
if(i + r[i] > R) R = i + r[i],pos = i;
}
}
}
char c[maxn];
int main(){
scanf("%s",c + 1);
Manacher(c);
int ans = 0;
for(int i=1;i<=len;i++) ans = max(ans,r[i]);
printf("%d\n",ans);
return 0;
}
kmp
here
/*知识点:kmp*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 2e6 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int border[maxn];
char s1[maxn],s2[maxn],inp[maxn];
inline void kmp(char *s){
int len = strlen(s + 1);
for(int i=2;i<=len;i++){
int pre = border[i - 1];
while(pre && s[pre + 1] != s[i]) pre = border[pre];
if(pre) border[i] = pre + 1;
else if(s[1] == s[i]) border[i] = 1;
}
}
int main(){
scanf("%s",s1 + 1);
scanf("%s",s2 + 1);
int len1 = strlen(s1 + 1),len2 = strlen(s2 + 1);
for(int i=1;i<=len2;i++) inp[i] = s2[i];
inp[len2 + 1] = '#';
for(int i=1;i<=len1;i++) inp[i + len2 + 1] = s1[i];
kmp(inp);
for(int i=len2+2;i<=len1+len2+1;i++)
if(border[i] == len2) printf("%d\n",i - len2 * 2);
for(int i=1;i<=len2;i++) border[i] = 0;
kmp(s2);
for(int i=1;i<=len2;i++) printf("%d ",border[i]);
return 0;
}
失配树(Fail 树)
here
/*知识点:kmp,失配树*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 1e6 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int border[maxn],len;
char c[maxn];
inline void kmp(char *s){
len = strlen(s + 1);
for(int i=2;i<=len;i++){
int pre = border[i - 1];
while(pre && s[i] != s[pre + 1]) pre = border[pre];
if(pre) border[i] = pre + 1;
else if(s[i] == s[1]) border[i] = 1;
}
}
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
inline void build(){
for(int i=1;i<=len;i++){
add(i + 1,border[i] + 1);
add(border[i] + 1,i + 1);
}
}
int fa[maxn][25],deep[maxn];
inline void dfs(int u,int Fa){
deep[u] = deep[Fa] + 1;
fa[u][0] = Fa;
for(int i=1;i<=20;i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == Fa) continue;
dfs(v,u);
}
}
inline int lca(int u,int v){
if(deep[u] < deep[v]) swap(u,v);
for(int i=20;i>=0;i--)
if(deep[fa[u][i]] >= deep[v])
u = fa[u][i];
if(u == v) return u;
for(int i=20;i>=0;i--)
if(fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int q;
int main(){
scanf("%s",c + 1);
kmp(c);
build();
dfs(1,0);
read(q);
while(q--){
int u,v;
read(u,v);
u++,v++;
int Lca = lca(u,v);
if(deep[u] > deep[v]) swap(u,v);
if(Lca == u) Lca = fa[Lca][0];
printf("%d\n",Lca - 1);
}
return 0;
}
exkmp
here
/*知识点:exkmp*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
const int maxn = 4e7 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c=getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48),c = getchar(); } x *= f;
}
template <typename T,typename... Args>
inline void read(T &x, Args&... Arg){read(x),read(Arg...); }
int lcp[maxn];
char a[maxn],b[maxn],c[maxn];
inline void exkmp(char *s){
int len = strlen(s + 1);
int R = 0,pos = 0;
for(int i=2;i<=len;i++){
if(i > R){
while(i + lcp[i] <= len && s[i + lcp[i]] == s[lcp[i] + 1]) lcp[i]++;
if(i + lcp[i] - 1 > R) R = i + lcp[i] - 1,pos = i;
}
else{
if(lcp[i - pos + 1] < R - i + 1) lcp[i] = lcp[i - pos + 1];
else{
lcp[i] = R - i + 1;
while(i + lcp[i] <= len && s[i + lcp[i]] == s[lcp[i] + 1]) lcp[i]++;
}
if(i + lcp[i] - 1 > R) R = i + lcp[i] - 1,pos = i;
}
}
}
int main(){
scanf("%s",a + 1);
scanf("%s",b + 1);
int lena = strlen(a + 1),lenb = strlen(b + 1);
exkmp(b);
ll ans = 0;
lcp[1] = lenb;
for(int i=1;i<=lenb;i++) ans ^= i * 1ll * (lcp[i] + 1ll);
printf("%lld\n",ans);
for(int i=1;i<=lenb;i++) c[i] = b[i],lcp[i] = 0;
c[lenb + 1] = '#';
for(int i=1;i<=lena;i++) c[i + lenb + 1] = a[i];
exkmp(c);
ans = 0;
for(int i=lenb+2;i<=lena+lenb+1;i++) ans ^= (i - lenb - 1) * 1ll * (lcp[i] + 1ll);
printf("%lld\n",ans);
return 0;
}