給出乙個字串,求出所有出現次數不為1的子串,長度×出現次數的最大值
$1\leq |s| \leq 1000 000$
用sam求出所有子串出現的次數即可
#includeusing namespace std;const int n=2*1e6+10;typedef long long ll;char s[n];
struct suffixautomation
inline void ins(int c,int pos)
//然後順著parent樹的路徑向上找
if(p==0)int q=mp[p][c];//case1
if(len[p]+1==len[q])//case2
len[++ct]=len[p]+1;//case 3
for(int i=1;i<=26;i++)
fa[ct]=fa[q];fa[q]=ct;fa[ed]=ct;
for(int i=p;mp[i][c]==q;i=fa[i])
}void solve()
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()
#include#define ll long longusing 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)
slink[n] = _slink;
return n++;
}int add_char(char ch, int u)
if(v == -1)
int x = trans[v][c];
if(maxlen[v] + 1 == maxlen[x])
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)
minlen[y] = maxlen[slink[y]] + 1;
return z;
}int main()
for(int i=1;iif(endps[i]!=1)ans=max(ans,(ll)endps[i]*maxlen[i]);
printf("%lld\n",ans);
return 0;
}
P3804 模板 字尾自動機
計算出現次數 1的子串長度 次數的最大值 sam 乙個串的出現次數等於right endpos集合的大小 而這個集合的大小等於所有parent樹上兒子的大小 這樣子的話,給每個終止位置的size記為1 然後按照拓撲序累加,這就是right endpos集合的大小 最後對於每個size 1的節點,an...
P3804 模板 字尾自動機 SAM
長度為n nn的串,求乙個出現次數不小於2的子串使得子串長度乘上出現次數最大。構建s am samsa m的時候統計一下每個子串出現多少次即可。include include include using namespace std const int n 2e6 10 int n,cnt,num n...
洛谷P3804 模板 字尾自動機
題意 求字串 s 中所有出現次數不為 1 的子串的出現次數乘上該子串長度的最大值。方法 建立sam,令葉子節點 size 等於 1。按照拓撲序從下往上計數。個數大於1的就累計結果。include include include using namespace std define n 1000010...