https://www.luogu.org/problem/P3804
给出一个字符串,求出所有出现次数不为1的子串,长度×出现次数的最大值
$1\leq |S| \leq 1000 000$
用SAM求出所有子串出现的次数即可
#include<bits/stdc++.h> using namespace std;const int N=2*1e6+10;typedef long long ll; char S[N]; struct suffixautomation { int mp[N][30];int fa[N];int ed;int ct;int len[N];int siz[N];int deg[N]; suffixautomation(){ed=ct=1;} inline void ins(int c,int pos) { int p=ed;siz[ed=++ct]=1;len[ed]=pos;//先初始化size和len for(;p&&mp[p][c]==0;p=fa[p]){mp[p][c]=ed;}//然后顺着parent树的路径向上找 if(p==0){fa[ed]=1;return;}int q=mp[p][c];//case1 if(len[p]+1==len[q]){fa[ed]=q;return;}//case2 len[++ct]=len[p]+1;//case 3 for(int i=1;i<=26;i++){mp[ct][i]=mp[q][i];} fa[ct]=fa[q];fa[q]=ct;fa[ed]=ct; for(int i=p;mp[i][c]==q;i=fa[i]){mp[i][c]=ct;} } void solve(){ queue<int>que; for(int i=2;i<=ct;i++)deg[fa[i]]++; for(int i=1;i<=ct;i++)if(deg[i]==0)que.push(i); while(que.size()){ int x=que.front(); que.pop(); if(x==1)break; int y=fa[x]; siz[y]+=siz[x]; deg[y]--; if(deg[y]==0)que.push(y); } ll ans=0; for(int i=1;i<=ct;i++)if(siz[i]>1)ans=max(ans,(ll)len[i]*siz[i]); printf("%lld\n",ans); } }sam; int main() { scanf("%s",S+1);//没啥好说的,建sam然后dfs int len=strlen(S+1); for(int i=1;i<=len;i++)sam.ins(S[i]-‘a‘+1,i); sam.solve(); return 0;//拜拜程序~ }
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXL = 1000000; string s; int n = 0,len,st; int maxlen[2 * MAXL + 10], minlen[2 * MAXL + 10], trans[2 * MAXL + 10][26], slink[2 * MAXL + 10]; int endps[2 * MAXL +10],deg[2* MAXL+10]; int new_state(int _maxlen, int _minlen, int* _trans, int _slink) { maxlen[n] = _maxlen; minlen[n] = _minlen; for(int i = 0; i < 26; i++) { if(_trans == NULL) trans[n][i] = -1; else trans[n][i] = _trans[i]; } slink[n] = _slink; return n++; } int add_char(char ch, int u) { int c = ch - ‘a‘; int z = new_state(maxlen[u] + 1, -1, NULL, -1); int v = u; while(v != -1 && trans[v][c] == -1) { trans[v][c] = z; v = slink[v]; } if(v == -1) { //最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移 minlen[z] = 1; slink[z] = 0; return z; } int x = trans[v][c]; if(maxlen[v] + 1 == maxlen[x]) { //较简单的情况,不用拆分x minlen[z] = maxlen[x] + 1; slink[z] = x; return z; } int y = new_state(maxlen[v] + 1, -1, trans[x], slink[x]); //最复杂的情况,拆分x slink[y] = slink[x]; minlen[x] = maxlen[y] + 1; slink[x] = y; minlen[z] = maxlen[y] + 1; slink[z] = y; int w = v; while(w != -1 && trans[w][c] == x) { trans[w][c] = y; w = slink[w]; } minlen[y] = maxlen[slink[y]] + 1; return z; } int main(){ int u=new_state(0,0,NULL,-1); cin>>s; len=s.size(); for(int i=0;i<len;i++){ u=add_char(s[i],u); endps[u]=1; } ll ans=0; for(int i=1;i<n;i++){ deg[slink[i]]++; } queue<int>que; for(int i=1;i<n;i++) if(deg[i]==0)que.push(i); while(que.size()){ int x=que.front(); que.pop(); if(x==0)break; endps[slink[x]]+=endps[x]; deg[slink[x]]--; if(deg[slink[x]]==0)que.push(slink[x]); } for(int i=1;i<n;i++) if(endps[i]!=1)ans=max(ans,(ll)endps[i]*maxlen[i]); printf("%lld\n",ans); return 0; }
原文:https://www.cnblogs.com/carcar/p/11631160.html