目錄雖然不知道失配樹是什麼,看這題是為數不多的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...