《雙點醫院》開發商新作《雙點大學》洩露 登陸主機和PC
阿新 • • 發佈:2021-05-31
考慮先把\(SAM\)建出來。
然後考慮怎麼統計答案。
首先考慮每個等價類,如果他沒有兒子的話,那麼他必定只出現了一次。而對於不是葉子節點的等價類,該等價類出現的次數為兒子出現次數的和。
那麼我們只要在link樹上\(dfs\)就行了,考慮每個等價類內挑最長的子串長度即\(len_u\)來計入答案。
【模板】字尾自動機 (SAM)
#include<iostream> #include<cstdio> #include<cstring> #define ll int #define N 1000005 #define fa link ll ch[N << 1][30];//tire樹的轉移 ll link[N << 1],len[N << 1],v[N << 1]; ll node = 1,lst = 1; ll cnt,head[N << 1]; struct P{int to,next;}e[N << 1]; inline void insert(int c){ int p = lst,q = ++node;lst = q; len[q] = len[p] + 1,v[q] = 1; while(!ch[p][c] && p != 0){//向上找 ch[p][c] = q; p = link[p]; } if(p == 0) link[q] = 1; else{ int x = ch[p][c]; if(len[p] + 1 == len[x]){ link[q] = x; }else{ int y = ++ node ;//複製一個新節點 link[y] = link[x]; link[x] = link[q] = y; len[y] = len[p] + 1; std::memcpy(ch[y],ch[x],sizeof(ch[x])); while(p != 0 && ch[p][c] == x){ ch[p][c] = y; p = link[p]; } } } } inline void add(int x,int y){ e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt; } char s[N]; ll ans; inline void dfs(int u){ if(head[u] == 0) v[u] = 1; else{ for(int i = head[u];i;i = e[i].next){ dfs(e[i].to); v[u] += v[e[i].to]; } ans = std::max(ans,len[u] * v[u]); } } int main(){ freopen("q.in","r",stdin); freopen("q.out","w",stdout); scanf("%s",s + 1); ll l = std::strlen(s + 1); for(int i = 1;i <= l;++i) insert(s[i] - 'a'); for(int i = 1;i <= node;++i) add(link[i],i); dfs(1); std::cout<<ans<<std::endl; }