P5829 模板 失配樹

2022-07-11 22:24:14 字數 1417 閱讀 8710

目錄雖然不知道失配樹是什麼,看這題是為數不多的kmp練手的"能做的題"之一,就把這道題切了

傳送門個人覺得題目已經非常簡潔明瞭,感動,就不再重複題意

kmp+lca

先推一道題,對這題應該有幫助:傳送門

kmp中,next[i]是由next[1~i-1]得到的,若next[i]next[j]得到,我們看成i是j的子節點next陣列求解完成後,我們就有了一棵樹(這就是標籤"樹形結構"的原因)

題目要我們求的是某兩個字首的最長公共"border",其實就是求連個點的lca,自己仔細想想

簡單寫乙個倍增lca,滿分**就出來了

關於kmp+倍增的事情這裡不詳細講,在上面推的題有提到

這道題其實真的不難,應該是我做過為數不多的紫題裡最水的一道,其實跟上面推的那道題是乙個檔次的

直接摳了p3435的**改一改就交了

#include #include #include #define nn 1000010

#define rr register

#define ll long long

using namespace std;

int sread(char *s)

int read()

int next[nn][30] ;

int siz[nn];

int dep[nn];

char s[nn];

int n , m;

int main()

/* for(int i = 1 ; i <= n ; i++)

cout << dep[i] << '\t';

return 0;*/

int k = log(n) / log(2) + 1;

for(int j = 1 ; j <= k ; j++)

for(int i = 1 ; i <= n ; i++)

m = read();

while(m--)

int t = log(dep[v]) / log(2);

for(int i = t ; i >= 0 ; i--)

if(dep[next[v][i]] >= dep[u])

v = next[v][i];

if(u == v)

t = log(dep[v]) / log(2);

for(int i = t ; i >= 0 ; i--)

if(next[v][i] != next[u][i])

u = next[u][i],

v = next[v][i];

printf("%d\n" , next[u][0]); }

return 0;

}

P5829 模板 失配樹

p5829 模板 失配樹 參考題解 我們先想乙個問題 如何求出乙個字串的所有border?如果乙個字串既是 s的字首又是 s 的字尾,那麼我們把 ss 自己平移一下就可以前後重合,然後我們就可以繼續匹。這不就是kmp嗎 求兩個字首的最長公共border,先對原串進行kmp,通過跳兩個字首的next求...

P5829 模板 失配樹

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

洛谷P5829 失配樹

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