#include <bits/stdc++.h>
using namespace std;
template <int len>
struct SAM {
struct Node {
int lnk, lmx;
bool is_copied;
int grf[26];
Node() {
lnk = lmx = is_copied = 0;
memset(grf, -1, sizeof(grf));
}
Node(int lnk, int lmx) {
this->lnk = lnk;
this->lmx = lmx;
is_copied = 0;
memset(grf, -1, sizeof(grf));
}
};
vector<Node> t;
vector<int> tr[len * 2 + 10];
int full;
SAM() {
int full = 0;
t.push_back(Node(-1, 0));
}
void insert(char c) {
t.push_back(Node(-1, t[full].lmx + 1));
int id = t.size() - 1;
int p = full;
while (p != -1 && t[p].grf[c - 'a'] == -1)
t[p].grf[c - 'a'] = id, p = t[p].lnk;
if (p == -1) {
t[id].lnk = 0;
tr[0].push_back(id);
full = id;
return;
}
int q = t[p].grf[c - 'a'];
if (t[q].lmx == t[p].lmx + 1) {
t[id].lnk = q;
tr[q].push_back(id);
} else {
t.push_back(Node(t[q].lnk, t[p].lmx + 1));
memcpy(t[t.size() - 1].grf, t[q].grf, sizeof(t[q].grf));
t[t.size() - 1].is_copied = 1;
t[id].lnk = t.size() - 1;
tr[t[q].lnk].push_back(t.size() - 1);
tr[t.size() - 1].push_back(id);
}
full = id;
}
};
const int N = 1000005;
SAM<N> sam;
int cnt[N * 2 + 10];
void get_cnt(int u) {
cnt[u] = 1;
for (int v : sam.tr[u])
get_cnt(v), cnt[u] += cnt[v];
}
int main() {
string s;
cin >> s;
for (char c : s) sam.insert(c);
get_cnt(0);
long long ans = 0;
for (int i = 0; i < sam.t.size(); i++)
if (cnt[i] != 1) ans = max(ans, 1ll * cnt[i] * sam.t[i].lmx);
cout << ans << endl;
}