传送门 to Vjudge.
曾经研究过这个问题,然而记不起来了......今天对着一个点想了很久。
为什么每次匹配一个字符串的时候要用一个 tmp[]
存下最大值而不能直接更新 mn[]
?因为匹配一个串的时候,在某些情况下我们不可避免地会走到同一个点,这个时候就应该从两次中取较大的一次。
另,每次匹配完之后需要更新父亲,因为儿子(更长的)都能被匹配到,那么父亲为什么不能被匹配呢?
不能在最后上传,留作思考。
const int maxn=200000; // twice const int sigma=26; const int inf=0x3f3f3f3f; int trie[maxn+5][sigma], fa[maxn+5]; int len[maxn+5], mn[maxn+5], tmp[maxn+5]; int ncnt=1, lst=1; inline void add(int c){ int p=lst, u=lst=++ncnt; len[u]=len[p]+1; for(; p && !trie[p][c]; p=fa[p]) trie[p][c]=u; if(!p) fa[u]=1; else{ int q=trie[p][c]; if(len[q]==len[p]+1) fa[u]=q; else{ int nq=++ncnt; mmcpy(trie[nq], trie[q]); fa[nq]=fa[q], len[nq]=len[p]+1; fa[q]=fa[u]=nq; for(; p && trie[p][c]==q; p=fa[p]) trie[p][c]=nq; } } } char s[maxn+5]; int n; vector<int>g[maxn+5]; inline void buildTre(){ rep(i, 2, ncnt) g[fa[i]].push_back(i); } /** @brief update @p mn[] */ void dfs(int u){ for(int v: g[u]) dfs(v), mn[u]=max(mn[u], mn[v]); } inline void buildSAM(){ rep(i, 1, n) add(s[i]-'a'); rep(i, 1, ncnt) mn[i]=inf; buildTre(); } inline void compare(){ int u=1, cur_len=0; rep(i, 0, ncnt) tmp[i]=0; rep(i, 1, n){ int to=s[i]-'a'; while(u && !trie[u][to]) u=fa[u], cur_len=min(cur_len, len[u]); if(!u) u=1, cur_len=0; else u=trie[u][to], ++cur_len; tmp[u]=max(tmp[u], cur_len); } rep(i, 2, ncnt) mn[i]=min(mn[i], tmp[i]); dfs(1); // update @p mn[] } signed main(){ int fir=1; while(~scanf("%s", s+1)){ n=strlen(s+1); if(fir) buildSAM(), fir=0; else compare(); } // dfs(1); int ans=0; rep(i, 2, ncnt) if(mn[i]<inf) ans=max(ans, mn[i]); writc(ans); return 0; }