給定一長為 \(n(n\leq 10^6)\) 的字串 \(s\),\(m(m\leq 5\times 10^5)\)次詢問,每次詢問它的兩個字首的最長公共 border。
先跑一遍kmp求出\(fail\)陣列,每個\(pos\)向\(fail[pos]\)連邊,建出\(fail\)樹,在\(fail\)樹上求lca即為兩個字首的最長公共border。
#include #include #include #include #include #include using namespace std;
#define rg register int
#define ll long long
templateinline void read(elemtype &t)
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
t=(w?-x:x);
}const int maxn=1000010;
struct graph;
edge g[maxn<<1];
int head[maxn];
int cnt;
graph():cnt(2){}
void clear(int node_num=0)
void add_edge(int u,int v)
};namespace kmp
inline void get_fail()
}};graph g;
char s[maxn];
int fail[maxn];
int n,m;
int deep[1000010],anc[1000010][20];
void dfs_init(int u,int fa)
return;
}int lca(int u,int v)
if(u==v) return u;
for(rg i=19;i>=0;--i)
}return anc[u][0];
}int main()
dfs_init(n+1,0);
read(m);
while(m--)
}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 模板 失配樹
目錄雖然不知道失配樹是什麼,看這題是為數不多的kmp練手的 能做的題 之一,就把這道題切了 傳送門個人覺得題目已經非常簡潔明瞭,感動,就不再重複題意 kmp lca 先推一道題,對這題應該有幫助 傳送門 kmp中,next i 是由next 1 i 1 得到的,若next i 由next j 得到,...