P5829 模板 失配樹

2021-10-19 12:25:58 字數 2448 閱讀 3173

p5829 【模板】失配樹

參考題解

我們先想乙個問題:如何求出乙個字串的所有border?

如果乙個字串既是 s的字首又是 s 的字尾,那麼我們把 ss 自己平移一下就可以前後重合,然後我們就可以繼續匹。。。。。這不就是kmp嗎

求兩個字首的最長公共border,

先對原串進行kmp,通過跳兩個字首的next求到兩個字首的所有border

我們通過next陣列構建一棵樹(發現這就是只有乙個字串的ac自動機的fail樹,所有我們也叫它fail樹),容易發現兩個字首的最長公共border就是他們在fail樹上的lca

綜上所述:

對原串kmp一遍,求的next陣列

構建fail樹

在fail數上跑lca

#include

#include

#include

#include

#include

#include

using

namespace std;

#define set(a) memset(a,0,sizeof(a))

#define f(i,a,b) for(register int i=a,i##end=b;i<=i##end;++i)

#define uf(i,a,b) for(register int i=a,i##end=b;i>=i##end;--i)

#define openf(a) freopen(#a

".in"

,"r"

,stdin)

;freopen

(#a".out"

,"w"

,stdout)

#define re register

#define ri re int

#define il inline

typedef long

long ll;

typedef unsigned long

long ull;

template inline t

rd(t& x)

ll rd()

inline int

max(

int a,

int b)

inline int

min(

int a,

int b)

const

int inf=

1<

<30;

const

int n=

1000005

;int next[n]

,n,m;

char s[n]

;int fa[n]

;int

get(

int x)

void

merge

(int x,

int y)

bool vis[n]

;int head[n]

,to[

2*n]

,nxt[

2*n]

,tot;

void

add(

int u,

int v)

//graph

int head2[n]

,to2[

2*n]

,nxt2[

2*n]

,num[

2*n]

,tot2;

void

add2

(int u,

int v,

int w)

//query

int ans[n]

,x[n

],y[n]

;void

tarjan

(int x)

for(ri i=head2[x]

;i;i=nxt2[i])if

(vis[to2[i]

]) ans[num[i]]=

get(to2[i]);

}int

main()

f(i,

1,n)

add(next[i]

,i);

rd(m);f

(i,1

,m)tarjan(0

);f(i,

1,m)

printf

("%d\n"

,(ans[i]

==x[i]

||ans[i]

==y[i]

)?next[ans[i]

]:ans[i]);

return0;

}

P5829 模板 失配樹

p5829 模板 失配樹 求公共 border 求 border 我會,kmp 那麼我直接做 m 次 kmp。顯然會tle,但是我們也可以用 kmp 先求一下原串的 border 然後我們可以發現,border 的 border 也是 border 那麼我們可以利用這個關係建一棵樹,然後我們可以發現...

P5829 模板 失配樹

目錄雖然不知道失配樹是什麼,看這題是為數不多的kmp練手的 能做的題 之一,就把這道題切了 傳送門個人覺得題目已經非常簡潔明瞭,感動,就不再重複題意 kmp lca 先推一道題,對這題應該有幫助 傳送門 kmp中,next i 是由next 1 i 1 得到的,若next i 由next j 得到,...

洛谷P5829 失配樹

給定一長為 n n leq 10 6 的字串 s m m leq 5 times 10 5 次詢問,每次詢問它的兩個字首的最長公共 border。先跑一遍kmp求出 fail 陣列,每個 pos 向 fail pos 連邊,建出 fail 樹,在 fail 樹上求lca即為兩個字首的最長公共bord...