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