#include using namespace std; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() typedef long long ll; typedef pair pii; typedef pair pll; typedef vector vi; typedef vector vl; typedef long double ld; int n; const int MAXN = 1000003; typedef uint64_t ull; struct H { ull x; H(ull x=0) : x(x) {} H operator+(H o) { return x + o.x + (x + o.x < x); } H operator-(H o) { return *this + ~o.x; } H operator*(H o) { auto m = (__uint128_t)x * o.x; return H((ull)m) + (ull)(m >> 64); } ull get() const { return x + !~x; } bool operator==(H o) const { return get() == o.get(); } bool operator<(H o) const { return get() < o.get(); } }; static const H C = (ll)1e11+3; // (order ~ 3e9; random also ok) struct HashInterval { vector ha, pw; HashInterval(string& str) : ha(sz(str)+1), pw(ha) { pw[0] = 1; rep(i,0,sz(str)) ha[i+1] = ha[i] * C + str[i], pw[i+1] = pw[i] * C; } H hashInterval(int a, int b) { // hash [a, b) return ha[b] - ha[a] * pw[b - a]; } }; vector getHashes(string& str, int length) { if (sz(str) < length) return {}; H h = 0, pw = 1; rep(i,0,length) h = h * C + str[i], pw = pw * C; vector ret = {h}; rep(i,length,sz(str)) { ret.push_back(h = h * C + str[i] - pw * str[i-length]); } return ret; } H hashString(string& s){H h{}; for(char c:s) h=h*C+c;return h;} string s; ll NUM[10] = {0}; ll CH[52] = {0}; void upd_num(ll x){ while(x > 0){ NUM[x%10]++; x /= 10; } } int ch_to_int(char ch){ if(ch <= 'Z')return ch-'A'; return ch-'a'+26; } string alfa = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; map M; vl F; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> s; n = sz(s); HashInterval HI(s); vl CS(n+1, 0); rep(c1,0,n){ rep(c2,c1,n){ H h = HI.hashInterval(c1,c2+1); if(M.find(h) == M.end()){ M[h] = sz(F); F.push_back(1); CS[c1]++; CS[c2+1]--; } else{ F[M[h]]++; } } } rep(c1,0,sz(F)){ upd_num(F[c1]); } rep(c1,0,n){ CH[ch_to_int(s[c1])] += CS[c1]; CS[c1+1] += CS[c1]; } rep(c1,0,10){ if(NUM[c1] != 0)cout << c1 << " " << NUM[c1] << "\n"; } rep(c1,0,52){ if(CH[c1] != 0)cout << alfa[c1] << " " << CH[c1] << "\n"; } return 0; }