//     package com.company;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.lang.reflect.Array;
    import java.sql.SQLOutput;
    import java.util.*;
    public class Main {

        public static void main(String[] args) throws IOException {
            Scanner s = new Scanner(System.in);
            //BufferedReader s=new BufferedReader(new InputStreamReader(System.in));
            StringBuilder sb1 = new StringBuilder();//int n=Integer.parseInt(s.readLine());
          char[] a=s.next().toCharArray();
          long[][] ans=new long[123][123];
            long[] [] count=new long[123][a.length];long fans=0;
       for(int i=0;i<a.length;i++){
           if(i==0){
               count[a[i]][0]=1;continue;
           }
           for(int j=97;j<123;j++){
               if(j==a[i]){
                   count[j][i]=count[a[i]][i-1]+1;
               }else count[j][i]=count[j][i-1];
           }
       }
          for(int i=0;i<a.length;i++){
              for(int j=97;j<123;j++){
                  if(j!=a[i]){
                  ans[a[i]][j]=ans[a[i]][j]+count[j][i];
//                      System.out.println(ans[a[i]][j]+" "+i+" "+a[i]+" "+j);

                      fans=Math.max(fans,ans[a[i]][j]);}
                  else{
                      ans[a[i]][j]=ans[a[i]][j]+count[j][i]-1;
    //                 System.out.println(ans[a[i]][j]+" "+i+" "+a[i]+" "+j);
                      fans=Math.max(fans,ans[a[i]][j]);}
                 fans=Math.max(fans,count[j][i]);
              }
          }
            System.out.println(fans);

        }static long ans=0;static long count=0;
        static void dfs(int i,ArrayList<Integer>[] adj,int[] vis,int n){
            vis[i]=1;
            if(adj[i]==null){return;}
            for(Integer j:adj[i]){
                if(vis[j]==0){
                     dfs(j,adj,vis,n);
                }
            }}
        static  void computeLPSArray(String pat, int M, int lps[])
        {
            int len = 0;
            int i = 1;
            lps[0] = 0;
            while (i < M) {
                if (pat.charAt(i) == pat.charAt(len)) {
                    len++;
                    lps[i] = len;
                    i++;
                }
                else // (pat[i] != pat[len])
                {
                    if (len != 0) {
                        len = lps[len - 1];
                    }
                    else // if (len == 0)
                    {
                        lps[i] = len;
                        i++;
                    }
                }
            }
        }
        static boolean isPrime(int n)
        {
            if (n <= 1) return false;
            if (n <= 3) return true;

            if (n % 2 == 0 || n % 3 == 0) return false;

            for (int i = 5; i * i <= n; i = i + 6)
                if (n % i == 0 || n % (i + 2) == 0)
                    return false;

            return true;
        }

        static double power(double x, long y, int p) {
            double res = 1;
            x = x % p;
            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }
        public static void fracion(double x) {
            String a = "" + x;
            String spilts[] = a.split("\\."); // split using decimal
            int b = spilts[1].length(); // find the decimal length
            int denominator = (int) Math.pow(10, b); // calculate the denominator
            int numerator = (int) (x * denominator); // calculate the nerumrator Ex
            // 1.2*10 = 12
            int gcd = (int)gcd((long)numerator, denominator); // Find the greatest common
            // divisor bw them
            String fraction = "" + numerator / gcd + "/" + denominator / gcd;
            // System.out.println((denominator/gcd));
            long x1=modInverse(denominator / gcd,998244353  );
            //  System.out.println(x1);
            System.out.println((((numerator / gcd )%998244353 *(x1%998244353  ))%998244353  ) );
        }static int anst=Integer.MAX_VALUE;
      static StringBuilder sb1=new StringBuilder();
        public static int bfs(int i1, ArrayList<Integer>[] h, int[] vis, int n,int val1) {
            Queue<Integer> q = new LinkedList<Integer>();
            q.add(i1);Queue<Integer> aq=new LinkedList<Integer>();
            aq.add(0);
            while(!q.isEmpty()){
                int i=q.poll();
                int val=aq.poll();
                if(i==n){
                    return val;
                }
                if(h[i]!=null){
                    for(Integer j:h[i]){
                       if(vis[j]==0){
                        q.add(j);vis[j]=1;
                           aq.add(val+1);}
                    }
                }
            }return -1;
        }
        static int i(String a) {
            return Integer.parseInt(a);
        }
        static long l(String a) {
            return Long.parseLong(a);
        }
        static String[] inp() throws IOException {
            BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
            return s.readLine().trim().split("\\s+");
        }

        static long gcd(long a, long b) {
            if (b == 0)
                return a;
            return gcd(b, a % b);
        }
        static long modInverse(int a, int m)
        {

            {
                // If a and m are relatively prime, then modulo inverse
                // is a^(m-2) mode m
                return (power(a, m - 2, m));
            }
        }

        // To compute x^y under modulo m
        static long power(int x, int y, int m)
        {
            if (y == 0)
                return 1;

            long p = power(x, y / 2, m) % m;
            p = (p * p) % m;

            if (y % 2 == 0)
                return p;
            else
                return (x * p) % m;
        }

        // Function to return gcd of a and b

    }
    class Student
    {
        int l;int r;
        public Student(int l, int r) {
            this.l = l;
            this.r = r;
        }
        // Constructor

        // Used to print student details in main()
        public String toString()
        {
            return this.l+" ";
        }
    }

    class Sortbyroll implements Comparator<Student>
    {
        // Used for sorting in ascending order of
        // roll number
        public int compare(Student a, Student b){
            return a.l-b.l;  }
    } class Sortbyroll1 implements Comparator<Student>
    {
        // Used for sorting in ascending order of
        // roll number
        public int compare(Student a, Student b){
            return a.l-b.l;
        }
    }


import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CowAndMessage{

    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static void main(String[] args){
        FastReader s = new FastReader();
        String str = s.next();
        int[] arr = new int[26];
        int[][] dp = new int[26][26];

        for(int i = 0;i<str.length();i++){
            int c = str.charAt(i)-'a';
            for(int j = 0;j<26;j++){
                dp[j][c] += arr[j];
            }
            arr[c]++;
        }
        int max = 0;
        for(int i = 0;i<arr.length;i++){
            max = Math.max(max, arr[i]);
        }

        for(int i = 0;i<dp.length;i++){
            for(int j = 0;j<dp[0].length;j++){
                max = Math.max(max, dp[i][j]);
            }
        }
        System.out.println(max);
    }

}


import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CowAndMessage{

    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static void main(String[] args){
        FastReader s = new FastReader();
        String str = s.next();
        long[] arr = new long[26];
        long[][] dp = new long[26][26];

        for(int i = 0;i<str.length();i++){
            int c = str.charAt(i)-'a';
            for(int j = 0;j<26;j++){
                dp[j][c] += arr[j];
            }
            arr[c]++;
        }
        long max = 0;
        for(int i = 0;i<arr.length;i++){
            max = Math.max(max, arr[i]);
        }

        for(int i = 0;i<dp.length;i++){
            for(int j = 0;j<dp[0].length;j++){
                max = Math.max(max, dp[i][j]);
            }
        }
        System.out.println(max);
    }

}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1307c {

    public static void main(String[] args) throws IOException {
        char[] s = rcha();
        int n = s.length, cnt[][] = new int[n + 1][26];
        long max = 0, cur;
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < 26; ++j) {
                cnt[i + 1][j] = cnt[i][j];
            }
            ++cnt[i + 1][s[i] - 'a'];
        }
        for(int i = 0; i < 26; ++i) {
            for(int j = 0; j < 26; ++j) {
                cur = 0;
                for(int k = 0; k < n; ++k) {
                    if(s[k] - 'a' == j) {
                        cur += cnt[k][i];
                    }
                }
                max = max(max, cur);
            }
        }

        prln(max(maxof(cnt[n]), max));
        close();
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IRAND ~= 3e8
    // IMAX ~= 2e10
    // LMAX ~= 9e18
    // constants
    static final int IBIG = 1000000007;
    static final int IRAND = 327859546;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static int minstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static long minstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static int maxstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static long maxstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static int powi(int a, int b) {if(a == 0) return 0; int ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if(a == 0) return 0; long ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int floori(double d) {return (int)d;}
    static int ceili(double d) {return (int)ceil(d);}
    static long floorl(double d) {return (long)d;}
    static long ceill(double d) {return (long)ceil(d);}
    static void shuffle(int[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static <T> void shuffle(T[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); T swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void sort(int[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(long[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(double[] a) {shuffle(a); Arrays.sort(a);}
    static void qsort(int[] a) {Arrays.sort(a);}
    static void qsort(long[] a) {Arrays.sort(a);}
    static void qsort(double[] a) {Arrays.sort(a);}
    static int randInt(int min, int max) {return rand.nextInt(max - min + 1) + min;}
    // input
    static void r() throws IOException {input = new StringTokenizer(__in.readLine());}
    static int ri() throws IOException {return Integer.parseInt(__in.readLine());}
    static long rl() throws IOException {return Long.parseLong(__in.readLine());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Integer.parseInt(input.nextToken()); return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Long.parseLong(input.nextToken()); return a;}
    static char[] rcha() throws IOException {return __in.readLine().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static int rni() throws IOException {input = new StringTokenizer(__in.readLine()); return Integer.parseInt(input.nextToken());}
    static int ni() {return Integer.parseInt(input.nextToken());}
    static long rnl() throws IOException {input = new StringTokenizer(__in.readLine()); return Long.parseLong(input.nextToken());}
    static long nl() {return Long.parseLong(input.nextToken());}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {__out.println("yes");}
    static void pry() {__out.println("Yes");}
    static void prY() {__out.println("YES");}
    static void prno() {__out.println("no");}
    static void prn() {__out.println("No");}
    static void prN() {__out.println("NO");}
    static void pryesno(boolean b) {__out.println(b ? "yes" : "no");};
    static void pryn(boolean b) {__out.println(b ? "Yes" : "No");}
    static void prYN(boolean b) {__out.println(b ? "YES" : "NO");}
    static void prln(int... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(long... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for(int i = 0; i < n; __out.print(iter.next()), __out.print(' '), ++i); if(n >= 0) __out.println(iter.next());}
    static void h() {__out.println("hlfd");}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1307c {

    public static void main(String[] args) throws IOException {
        char[] s = rcha();
        int n = s.length, cnt[][] = new int[n][26];
        long max = 0, cur;
        ++cnt[0][s[0] - 'a'];
        for(int i = 1; i < n; ++i) {
            for(int j = 0; j < 26; ++j) {
                cnt[i][j] = cnt[i - 1][j];
            }
            ++cnt[i][s[i] - 'a'];
        }
        for(int i = 0; i < 26; ++i) {
            for(int j = 0; j < 26; ++j) {
                if(i != j) {
                    cur = 0;
                    for(int k = 0; k < n; ++k) {
                        if(s[k] - 'a' == j) {
                            cur += cnt[k][i];
                        }
                    }
                    max = max(max, cur);
                }
            }
        }

        prln(max(maxof(cnt[n - 1]), max));
        close();
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IRAND ~= 3e8
    // IMAX ~= 2e10
    // LMAX ~= 9e18
    // constants
    static final int IBIG = 1000000007;
    static final int IRAND = 327859546;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static int minstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static long minstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static int maxstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static long maxstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static int powi(int a, int b) {if(a == 0) return 0; int ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if(a == 0) return 0; long ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int floori(double d) {return (int)d;}
    static int ceili(double d) {return (int)ceil(d);}
    static long floorl(double d) {return (long)d;}
    static long ceill(double d) {return (long)ceil(d);}
    static void shuffle(int[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static <T> void shuffle(T[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); T swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void sort(int[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(long[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(double[] a) {shuffle(a); Arrays.sort(a);}
    static void qsort(int[] a) {Arrays.sort(a);}
    static void qsort(long[] a) {Arrays.sort(a);}
    static void qsort(double[] a) {Arrays.sort(a);}
    static int randInt(int min, int max) {return rand.nextInt(max - min + 1) + min;}
    // input
    static void r() throws IOException {input = new StringTokenizer(__in.readLine());}
    static int ri() throws IOException {return Integer.parseInt(__in.readLine());}
    static long rl() throws IOException {return Long.parseLong(__in.readLine());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Integer.parseInt(input.nextToken()); return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Long.parseLong(input.nextToken()); return a;}
    static char[] rcha() throws IOException {return __in.readLine().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static int rni() throws IOException {input = new StringTokenizer(__in.readLine()); return Integer.parseInt(input.nextToken());}
    static int ni() {return Integer.parseInt(input.nextToken());}
    static long rnl() throws IOException {input = new StringTokenizer(__in.readLine()); return Long.parseLong(input.nextToken());}
    static long nl() {return Long.parseLong(input.nextToken());}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {__out.println("yes");}
    static void pry() {__out.println("Yes");}
    static void prY() {__out.println("YES");}
    static void prno() {__out.println("no");}
    static void prn() {__out.println("No");}
    static void prN() {__out.println("NO");}
    static void pryesno(boolean b) {__out.println(b ? "yes" : "no");};
    static void pryn(boolean b) {__out.println(b ? "Yes" : "No");}
    static void prYN(boolean b) {__out.println(b ? "YES" : "NO");}
    static void prln(int... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(long... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for(int i = 0; i < n; __out.print(iter.next()), __out.print(' '), ++i); if(n >= 0) __out.println(iter.next());}
    static void h() {__out.println("hlfd");}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}


import java.util.Scanner;

public class TaskC {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        String s = reader.next();
        int[] arr1 = new int[26];
        int[][] arr2 = new int[26][26];
        for (int i = 0; i < s.length(); i++) {
            int x = s.charAt(i) - 'a';
            for (int j = 0; j < 26; j++) {
                arr2[x][j] += arr1[j];
            }
            arr1[x]++;
        }
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            ans = Math.max(ans, arr1[i]);
        }
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < 26; j++) {
                ans = Math.max(ans, arr2[i][j]);
            }
        }
        System.out.println(ans);
    }
}


import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class Code {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String a = reader.readLine();

        int count = 0;
        for (char c = 'a'; c <= 'z'; c++) {
            StringBuilder sb = new StringBuilder();
            sb.append(c);
            int localCount = subsequenceCount(a, sb.toString());
            if (localCount == 0) continue;
            count = max(count, localCount);
            for (char d = 'a'; d <= 'z'; d++) {
                sb.append(d);
                count = max(count, subsequenceCount(a, sb.toString()));
                sb.setLength(1);
            }
        }
        System.out.println(count);
    }

    public static int subsequenceCount(String a, String b) {
        int n = a.length();
        int m = b.length();
        int[][] dp = new int[n + 1][m + 1];
        for (int i = 0; i <= n; i++) {
            dp[i][m] = 1;
        }

        for (int i = n - 1; i >= 0; i--) {
            for (int j = m - 1; j >= 0; j--) {
                if (a.charAt(i) == b.charAt(j)) {
                    dp[i][j] += dp[i + 1][j + 1];
                }

                dp[i][j] += dp[i + 1][j];
            }
        }

        return dp[0][0];
    }
}


import java.util.Scanner;

public class TaskC {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        String s = reader.next();
        long[] arr1 = new long[26];
        long[][] arr2 = new long[26][26];
        for (int i = 0; i < s.length(); i++) {
            int x = s.charAt(i) - 'a';
            for (int j = 0; j < 26; j++) {
                arr2[x][j] += arr1[j];
            }
            arr1[x]++;
        }
        long ans = 0;
        for (int i = 0; i < 26; i++) {
            ans = Math.max(ans, arr1[i]);
        }
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < 26; j++) {
                ans = Math.max(ans, arr2[i][j]);
            }
        }
        System.out.println(ans);
    }
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		long arr1[]=new long[26], arr2[][]=new long[26][26], max=0;;
		int l=arr.length;

		for(int i=0; i<l; i++) {
			for(int j=0; j<26; j++) {
				arr2[arr[i]-97][j]+=arr1[j];
			}
			arr1[arr[i]-97]++;
		}
		for(int i=0; i<26; i++)
			max=max(max, arr1[i]);
		for(int i=0; i<26; i++) {
			for(int j=0; j<26; j++)
				max=max(max, arr2[i][j]);
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {
        int i = 0, j = str.length() - 1;

        while (i < j) {

            if (str.charAt(i) != str.charAt(j))
                return false;

            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}
	public static long abs(long x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}
	public static long max(long a, long b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}
	public static long min(long a, long b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int l=arr.length, arr1[]=new int[26];
		for(int i=0; i<l; i++)
			arr1[arr[i]-97]++;

		if(l==1)
			out.println(1);

		else {
			Arrays.sort(arr1);
			out.println(Math.max((long)arr1[25]*arr1[24], (long)arr1[25]*(arr1[25]-1)/2));
		}
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray(), ch1='\0', ch2='\0';
		int l=arr.length, arr1[]=new int[26];
		long max1=0, max2=0, count1=0, count2=0, temp=0;

		for(int i=0; i<l; i++)
			arr1[arr[i]-97]++;

		for(int i=0; i<26; i++) {
			if(arr1[i]>max1) {
				max1=arr1[i];
				ch1=(char)(i+97);
			}
		}

		for(int i=0; i<26; i++) {
			if(arr1[i]!=max1 && arr1[i]>max2) {
				max2=arr1[i];
				ch2=(char)(i+97);
			}
		}
		//out.println(max1+" "+max2+" "+ch1+" "+ch2);
		if(ch2=='\0')
			out.println(Math.max(max1, max1*(max1-1)/2));
		else {
			temp=max2;
			for(int i=0; i<l; i++) {
				if(arr[i]==ch1)
					count1+=temp;
				if(arr[i]==ch2)
					temp--;
			}
			temp=max1;
			for(int i=0; i<l; i++) {
				//out.println(count1);
				if(arr[i]==ch2)
					count2+=temp;
				if(arr[i]==ch1)
					temp--;
			}
			out.println(Math.max(Math.max(max1, max1*(max1-1)/2), Math.max(count1, count2)));
		}
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int l=arr.length, max=0, temp;
		HashMap<String, Integer> hs = new HashMap<>();
		String str;

		for(int i=0; i<l; i++) {
			str=arr[i]+"";
			//out.println(str);
			if(!hs.containsKey(str)) {
				hs.put(str, 1);
				max=max(max, 1);
			}else {
				temp=hs.get(str)+1;
				hs.put(str, temp);
				max=max(max, temp);
			}

			for(int j=1; j<l-i; j++) {
				str=arr[i]+"";
				for(int k=i+j; k<l; k+=j) {
					str+=arr[k];
					//out.println(str);
					if(!hs.containsKey(str)) {
						hs.put(str, 1);
						max=max(max, 1);
					}else {
						temp=hs.get(str)+1;
						hs.put(str, temp);
						max=max(max, temp);
					}
				}
			}
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int arr1[]=new int[26], arr2[][]=new int[26][26], l=arr.length, max=0;

		for(int i=0; i<l; i++) {
			for(int j=0; j<26; j++) {
				arr2[arr[i]-97][j]+=arr1[j];
			}
			arr1[arr[i]-97]++;
		}
		for(int i=0; i<26; i++)
			max=max(max, arr1[i]);
		for(int i=0; i<26; i++) {
			for(int j=0; j<26; j++)
				max=max(max, arr2[i][j]);
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int arr1[]=new int[26], arr2[][]=new int[26][26], l=arr.length;
		long max=0;

		for(int i=0; i<l; i++) {
			for(int j=0; j<26; j++) {
				arr2[arr[i]-97][j]+=arr1[j];
			}
			arr1[arr[i]-97]++;
		}
		for(int i=0; i<26; i++)
			max=max(max, arr1[i]);
		for(int i=0; i<26; i++) {
			for(int j=0; j<26; j++)
				max=max(max, arr2[i][j]);
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}
	public static long abs(long x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}
	public static long max(long a, long b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}
	public static long min(long a, long b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int l=arr.length, arr1[]=new int[26];
		for(int i=0; i<l; i++)
			arr1[arr[i]-97]++;

		if(l==1)
			out.println(1);

		else {
			Arrays.sort(arr1);

			out.println(arr1[25]*arr1[24]);
		}
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int l=arr.length, max=0, temp;
		HashMap<String, Integer> hs = new HashMap<>();
		String str;

		for(int i=0; i<l; i++) {
			str=arr[i]+"";
			//out.println(str);
			if(!hs.containsKey(str)) {
				hs.put(str, 1);
				max=max(max, 1);
			}else {
				temp=hs.get(str)+1;
				hs.put(str, temp);
				max=max(max, temp);
			}

			for(int j=1; j<l-i; j++) {
				str=arr[i]+"";
				int k=i+j;
					str+=arr[k];
					//out.println(str);
					if(!hs.containsKey(str)) {
						hs.put(str, 1);
						max=max(max, 1);
					}else {
						temp=hs.get(str)+1;
						hs.put(str, temp);
						max=max(max, temp);
					}

			}
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Main{

	static int p=1000000007;

	public static void main (String args[])throws IOException{
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);

		char arr[]=sc.next().toCharArray();
		int l=arr.length, max=0, temp;
		HashMap<String, Integer> hs = new HashMap<>();
		String str;

		for(int i=0; i<l; i++) {
			str=arr[i]+"";
			//out.println(str);
			if(!hs.containsKey(str)) {
				hs.put(str, 1);
				max=max(max, 1);
			}else {
				temp=hs.get(str)+1;
				hs.put(str, temp);
				max=max(max, temp);
			}

			for(int j=1; j<l-i; j++) {
				if((long)max>(long)l/j*2*l)
					break;
				str=arr[i]+"";
				for(int k=i+j; k<l; k+=j) {
					str+=arr[k];
					//out.println(str);
					if(!hs.containsKey(str)) {
						hs.put(str, 1);
						max=max(max, 1);
					}else {
						temp=hs.get(str)+1;
						hs.put(str, temp);
						max=max(max, temp);
					}
				}
			}
		}
		out.println(max);
		out.flush();
	}

	public static String reverseString(String str){
	    StringBuilder sb=new StringBuilder(str);
	    sb.reverse();
	    return sb.toString();
	}

	static boolean isPalindrome(String str)
    {

        // Pointers pointing to the beginning
        // and the end of the string
        int i = 0, j = str.length() - 1;

        // While there are characters toc compare
        while (i < j) {

            // If there is a mismatch
            if (str.charAt(i) != str.charAt(j))
                return false;

            // Increment first pointer and
            // decrement the other
            i++;
            j--;
        }
        return true;
    }

	static void print(int[] arr) {
		for(int i=0; i<arr.length; i++)
			System.out.print(arr[i]+" ");
		System.out.println();
	}

	public static int abs(int x) {return ((x > 0) ? x : -x);}

	public static int max(int a, int b) {return Math.max(a, b);}

	public static int min(int a, int b) {return Math.min(a, b);}

	 static int gcd(int a, int b)
	    {
	        if (a == 0)
	            return b;
	        return gcd(b % a, a);
	    }

    static int modInverse(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return -1;
        else
        	return power(a, m - 2, m);

    }

    // To compute x^y under modulo m
    static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }

    static int[] primeGenerator(int num) {
    	int length=0, arr[]=new int[num], a=num, factor=1;
    	if(num%2==0) {
    		while(num%2==0) {
    			num/=2;
    			factor*=2;
    		}
    		arr[length++]=factor;
    	}
    	for(int i=3; i*i<=a; i++) {
    		factor=1;
    		if(num%i==0) {
        		while(num%i==0) {
        			num/=i;
        			factor*=i;
        		}
        		arr[length++]=factor;
    		}
    	}
    	if(num>1)
    		arr[length++]=num;
    	return Arrays.copyOfRange(arr, 0, length);
    }

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1)
            return false;
        if (n <= 3)
            return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0)
            return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
                return false;

        return true;
    }

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

	static void sort(int[] a) {
		shuffle(a);
		Arrays.sort(a);
	}

	static void shuffle(int[] a) {
		int n = a.length;
		Random rand = new Random();
		for (int i = 0; i < n; i++) {
			int tmpIdx = rand.nextInt(n);
			int tmp = a[i];
			a[i] = a[tmpIdx];
			a[tmpIdx] = tmp;
		}
	}
}

class Pair{
	int x;
	int y;
	Pair(int a, int b){
		x=a;
		y=b;
	}

	void print() {
		System.out.println(this.x+" "+this.y);
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.function.*;

public class C {

    private static final FastReader in = new FastReader();
    private static final FastWriter out = new FastWriter();

    public static void main(String[] args) {
        new C().run();
    }

    private void run() {
        var t = 1;
        while (t-- > 0) {
            solve();
        }

        out.flush();
    }

    private void solve() {
        var s = in.next();
        var n = s.length();

        var f = new long[n + 1][];
        f[n] = new long[26];

        for (var i = n - 1; i >= 0; i--) {
            f[i] = new long[26];
            var d = s.charAt(i) - 'a';
            for (var j = 0; j < 26; j++) {
                f[i][j] = f[i + 1][j] + (d == j ? 1 : 0);
            }
        }

        long ans = 0l;
        for (var j = 0; j < 26; j++) {
            ans = Math.max(ans, f[0][j]);
        }

        for (var a = 0; a < 26; a++) {
            for (var b = 0; b < 26; b++) {
                long count = 0;
                for (var i = 0; i < n; i++) {
                    if (s.charAt(i) - 'a' == a) {
                        count += f[i + 1][b];
                    }
                }
                ans = Math.max(ans, count);
            }
        }

        out.println(ans);
    }

}

class FastReader {

    private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static StringTokenizer in;

    public String next() {
        while (in == null || !in.hasMoreTokens()) {
            try {
                in = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return in.nextToken();
    }

    public BigDecimal nextBigDecimal() {
        return new BigDecimal(next());
    }

    public BigInteger nextBigInteger() {
        return new BigInteger(next());
    }

    public boolean nextBoolean() {
        return Boolean.valueOf(next());
    }

    public byte nextByte() {
        return Byte.valueOf(next());
    }

    public double nextDouble() {
        return Double.valueOf(next());
    }

    public double[] nextDoubleArray(int length) {
        var a = new double[length];
        for (var i = 0; i < length; i++) {
            a[i] = nextDouble();
        }
        return a;
    }

    public int nextInt() {
        return Integer.valueOf(next());
    }

    public int[] nextIntArray(int length) {
        var a = new int[length];
        for (var i = 0; i < length; i++) {
            a[i] = nextInt();
        }
        return a;
    }

    public long nextLong() {
        return Long.valueOf(next());
    }

    public long[] nextLongArray(int length) {
        var a = new long[length];
        for (var i = 0; i < length; i++) {
            a[i] = nextLong();
        }
        return a;
    }

}

class FastWriter extends PrintWriter {

    public FastWriter() {
        super(System.out);
    }

    public void println(double[] a) {
        for (var i = 0; i < a.length; i++) {
            print(a[i]);
            print(i + 1 < a.length ? ' ' : '\n');
        }
    }

    public void println(int[] a) {
        for (var i = 0; i < a.length; i++) {
            print(a[i]);
            print(i + 1 < a.length ? ' ' : '\n');
        }
    }

    public void println(long[] a) {
        for (var i = 0; i < a.length; i++) {
            print(a[i]);
            print(i + 1 < a.length ? ' ' : '\n');
        }
    }

    public <T> void println(T[] a) {
        for (var i = 0; i < a.length; i++) {
            print(a[i]);
            print(i + 1 < a.length ? ' ' : '\n');
        }
    }

    public void debug(String name, Object o) {
        String value = Arrays.deepToString(new Object[] { o });
        value = value.substring(1, value.length() - 1);
        System.err.println(name + " => " + value);
    }

}


// @uthor -: puneet
// TimeStamp -: 17/02/20

import java.io.*;
import java.util.*;

public class CombinedQ3 implements Runnable {

    private boolean testCases=false;
    private boolean console=false;

    public void solve() {

        char[] arr=in.ns().toCharArray();
        int n=arr.length;
        int[] freq = new int[26];
        long max=0;
        HashMap<String,Long> map=new HashMap<>();

        for(int k=0;k<n;++k){

            for(int i=0;i<26;++i){
                String str=""+(char)('a'+i)+arr[k];
                if(!map.containsKey(str)){
                    map.put(str,0L);
                }

                map.put(str,map.get(str)+freq[i]);
                max=Math.max(max,map.get(str));
            }
            freq[arr[k]-'a']++;
        }

        for(int i=0;i<26;++i){
            max=Math.max(max,freq[i]);
        }

        out.println(max);

    }

    /* -------------------- Templates and Input Classes -------------------------------*/

    @Override
    public void run() {
        try {
            init();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        int t= testCases ? in.ni() : 1;
        while (t-->0) {
            solve();
            out.flush();
        }
    }

    private FastInput in;
    private PrintWriter out;
    public static void main(String[] args) throws Exception {
        new Thread(null, new CombinedQ3(), "Main", 1 << 27).start();
    }
    private void init() throws FileNotFoundException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        try {
            if (!console && System.getProperty("user.name").equals("puneet")) {
                outputStream = new FileOutputStream("/home/puneet/Desktop/output.txt");
                inputStream = new FileInputStream("/home/puneet/Desktop/input.txt");
            }
        } catch (Exception ignored) {
        }
        out = new PrintWriter(outputStream);
        in = new FastInput(inputStream);
    }
    private void sort(int[] arr) {
        List<Integer> list = new ArrayList<>();
        for (int object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    private void sort(long[] arr) {
        List<Long> list = new ArrayList<>();
        for (long object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    public long ModPow(long x, long y, long MOD) {
        long res = 1L;
        x = x % MOD;
        while (y >= 1) {
            if ((y & 1) > 0) res = (res * x) % MOD;
            x = (x * x) % MOD;
            y >>= 1;
        }
        return res;
    }
    public int gcd(int a, int b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    public long gcd(long a, long b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    static class FastInput { InputStream obj;
        public FastInput(InputStream obj) {
            this.obj = obj;
        }
        byte inbuffer[] = new byte[1024];
        int lenbuffer = 0, ptrbuffer = 0;
        int readByte() { if (lenbuffer == -1) throw new InputMismatchException();
            if (ptrbuffer >= lenbuffer) { ptrbuffer = 0;
                try { lenbuffer = obj.read(inbuffer);
                } catch (IOException e) { throw new InputMismatchException(); } }
            if (lenbuffer <= 0) return -1;return inbuffer[ptrbuffer++]; }
        String ns() { int b = skip();StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) // when nextLine, (isSpaceChar(b) && b!=' ')
            { sb.appendCodePoint(b);b = readByte(); }return sb.toString();}
        int ni() {
            int num = 0, b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); }}
        long nl() { long num = 0;int b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10L + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); } }
        boolean isSpaceChar(int c) {
            return (!(c >= 33 && c <= 126));
        }
        int skip() { int b;while ((b = readByte()) != -1 && isSpaceChar(b)) ;return b; }
        float nf() {return Float.parseFloat(ns());}
        double nd() {return Double.parseDouble(ns());}
        char nc() {return (char) skip();}
    }

}


// @uthor -: puneet
// TimeStamp -: 17/02/20

import java.io.*;
import java.util.*;

public class CombinedQ3 implements Runnable {

    private boolean testCases=false;
    private boolean console=false;

    public void solve() {

        char[] arr=in.ns().toCharArray();
        int n=arr.length;
        int[] freq = new int[26];
        int max=0;
        HashMap<String,Integer> map=new HashMap<>();

        for(int k=0;k<n;++k){
            for(int i=0;i<26;++i){
                String str=""+(char)('a'+i)+arr[k];
                if(!map.containsKey(str)){
                    map.put(str,0);
                }

                map.put(str,map.get(str)+freq[i]);
                max=Math.max(max,map.get(str));
            }
            freq[arr[k]-'a']++;
        }

        for(int i=0;i<26;++i){
            max=Math.max(max,freq[i]);
        }

        out.println(max);

    }

    /* -------------------- Templates and Input Classes -------------------------------*/

    @Override
    public void run() {
        try {
            init();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        int t= testCases ? in.ni() : 1;
        while (t-->0) {
            solve();
            out.flush();
        }
    }

    private FastInput in;
    private PrintWriter out;
    public static void main(String[] args) throws Exception {
        new Thread(null, new CombinedQ3(), "Main", 1 << 27).start();
    }
    private void init() throws FileNotFoundException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        try {
            if (!console && System.getProperty("user.name").equals("puneet")) {
                outputStream = new FileOutputStream("/home/puneet/Desktop/output.txt");
                inputStream = new FileInputStream("/home/puneet/Desktop/input.txt");
            }
        } catch (Exception ignored) {
        }
        out = new PrintWriter(outputStream);
        in = new FastInput(inputStream);
    }
    private void sort(int[] arr) {
        List<Integer> list = new ArrayList<>();
        for (int object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    private void sort(long[] arr) {
        List<Long> list = new ArrayList<>();
        for (long object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    public long ModPow(long x, long y, long MOD) {
        long res = 1L;
        x = x % MOD;
        while (y >= 1) {
            if ((y & 1) > 0) res = (res * x) % MOD;
            x = (x * x) % MOD;
            y >>= 1;
        }
        return res;
    }
    public int gcd(int a, int b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    public long gcd(long a, long b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    static class FastInput { InputStream obj;
        public FastInput(InputStream obj) {
            this.obj = obj;
        }
        byte inbuffer[] = new byte[1024];
        int lenbuffer = 0, ptrbuffer = 0;
        int readByte() { if (lenbuffer == -1) throw new InputMismatchException();
            if (ptrbuffer >= lenbuffer) { ptrbuffer = 0;
                try { lenbuffer = obj.read(inbuffer);
                } catch (IOException e) { throw new InputMismatchException(); } }
            if (lenbuffer <= 0) return -1;return inbuffer[ptrbuffer++]; }
        String ns() { int b = skip();StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) // when nextLine, (isSpaceChar(b) && b!=' ')
            { sb.appendCodePoint(b);b = readByte(); }return sb.toString();}
        int ni() {
            int num = 0, b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); }}
        long nl() { long num = 0;int b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10L + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); } }
        boolean isSpaceChar(int c) {
            return (!(c >= 33 && c <= 126));
        }
        int skip() { int b;while ((b = readByte()) != -1 && isSpaceChar(b)) ;return b; }
        float nf() {return Float.parseFloat(ns());}
        double nd() {return Double.parseDouble(ns());}
        char nc() {return (char) skip();}
    }

}


// @uthor -: puneet
// TimeStamp -: 17/02/20

import java.io.*;
import java.util.*;

public class CombinedQ4 implements Runnable {

    private boolean testCases=false;
    private boolean console=false;

    public void solve() {
        int n=in.ni(),m=in.ni(),k=in.ni();
        int []arr=new int[k];

        ArrayList<Pair>[] list=new ArrayList[n+2];
        for(int i=0;i<n+2;++i){
            list[i]=new ArrayList<>();
        }
        for(int i=0;i<k;++i){
            arr[i]=in.ni();
        }
        for(int i=0;i<m;++i){
            int u=in.ni()-1,v=in.ni()-1;
            list[u].add(new Pair(v,1));
            list[v].add(new Pair(u,1));
        }
        int[] ans=dijkstra(0,n,list);
        int[] ans2=dijkstra(n-1,n,list);
        Pair2 []p=new Pair2[k];
        for(int i=0;i<k;++i){
            p[i]=new Pair2(ans[arr[i]-1],ans2[arr[i]-1],arr[i]);
        }

        Arrays.sort(p, (pair2, t1) -> pair2.w1-pair2.w1);

        int node1=p[0].node,node2=p[1].node;
        int mindist=Math.abs(p[0].w1-p[1].w1);
        for(int i=1;i<k-1;++i){
            if(Math.abs(p[i].w1-p[i+1].w1)<mindist){
                mindist=Math.abs(p[i].w1-p[i+1].w1);
                node1=p[i].node;
                node2=p[i+1].node;
            }
        }

        list[node1-1].add(new Pair(node2-1,1));
        list[node2-1].add(new Pair(node1-1,1));

        int[] fans1=dijkstra(0,n,list);
        list[node1-1].remove(list[node1-1].size()-1);
        list[node2-1].remove(list[node2-1].size()-1);

        Arrays.sort(p, (pair2, t1) -> pair2.w2-pair2.w2);

        node1=p[0].node;
        node2=p[1].node;
        mindist=Math.abs(p[0].w2-p[1].w2);
        for(int i=0;i<k-1;++i){
            if(Math.abs(p[i].w2-p[i+1].w2)<mindist){
                mindist=Math.abs(p[i].w2-p[i+1].w2);
                node1=p[i].node;
                node2=p[i+1].node;
            }
        }

        list[node1-1].add(new Pair(node2-1,1));
        list[node2-1].add(new Pair(node1-1,1));
        int[] fans2=dijkstra(0,n,list);
        out.println(Math.max(fans2[n-1],fans1[n-1]));

    }

    class Pair2{
        int w1=0,w2,node;

        public Pair2(int w1, int w2,int node) {
            this.w1 = w1;
            this.w2 = w2;
            this.node=node;
        }
    }

    int[] dijkstra(int start, int n, ArrayList<Pair>[] lis) {
        PriorityQueue<Pair> pq = new PriorityQueue<Pair>(n, Comparator.comparingDouble(pair -> pair.wt));

        int[] dist = new int[n];
        boolean[] vis = new boolean[n];

        pq.add(new Pair(start, 0));

        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[start] = 0;

        while (!pq.isEmpty()) {

            Pair p = pq.peek();
            pq.poll();

            int node = p.node;

            if (vis[node])
                continue;

            vis[node] = true;

            for (int i = 0; i < lis[node].size(); i++) {
                int ni = lis[node].get(i).node;
                int wi = lis[node].get(i).wt;

                if (!vis[ni]) {
                    if (dist[ni] > dist[node] + wi) {
                        dist[ni] = dist[node] + wi;
                        pq.add(new Pair(ni, dist[ni]));
                    }
                }
            }

        }

        return dist;

    }

    class Pair {

        int node;
        int wt;

        Pair(int node, int wt) {
            this.node = node;
            this.wt = wt;
        }

    }

    /* -------------------- Templates and Input Classes -------------------------------*/

    @Override
    public void run() {
        try {
            init();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        int t= testCases ? in.ni() : 1;
        while (t-->0) {
            solve();
            out.flush();
        }
    }

    private FastInput in;
    private PrintWriter out;
    public static void main(String[] args) throws Exception {
        new Thread(null, new CombinedQ4(), "Main", 1 << 27).start();
    }
    private void init() throws FileNotFoundException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        try {
            if (!console && System.getProperty("user.name").equals("puneet")) {
                outputStream = new FileOutputStream("/home/puneet/Desktop/output.txt");
                inputStream = new FileInputStream("/home/puneet/Desktop/input.txt");
            }
        } catch (Exception ignored) {
        }
        out = new PrintWriter(outputStream);
        in = new FastInput(inputStream);
    }
    private void sort(int[] arr) {
        List<Integer> list = new ArrayList<>();
        for (int object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    private void sort(long[] arr) {
        List<Long> list = new ArrayList<>();
        for (long object : arr) list.add(object);
        Collections.sort(list);
        for (int i = 0; i < list.size(); ++i) arr[i] = list.get(i);
    }
    public long ModPow(long x, long y, long MOD) {
        long res = 1L;
        x = x % MOD;
        while (y >= 1) {
            if ((y & 1) > 0) res = (res * x) % MOD;
            x = (x * x) % MOD;
            y >>= 1;
        }
        return res;
    }
    public int gcd(int a, int b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    public long gcd(long a, long b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    static class FastInput { InputStream obj;
        public FastInput(InputStream obj) {
            this.obj = obj;
        }
        byte inbuffer[] = new byte[1024];
        int lenbuffer = 0, ptrbuffer = 0;
        int readByte() { if (lenbuffer == -1) throw new InputMismatchException();
            if (ptrbuffer >= lenbuffer) { ptrbuffer = 0;
                try { lenbuffer = obj.read(inbuffer);
                } catch (IOException e) { throw new InputMismatchException(); } }
            if (lenbuffer <= 0) return -1;return inbuffer[ptrbuffer++]; }
        String ns() { int b = skip();StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) // when nextLine, (isSpaceChar(b) && b!=' ')
            { sb.appendCodePoint(b);b = readByte(); }return sb.toString();}
        int ni() {
            int num = 0, b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); }}
        long nl() { long num = 0;int b;boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') { minus = true;b = readByte(); }
            while (true) { if (b >= '0' && b <= '9') { num = num * 10L + (b - '0'); } else {
                    return minus ? -num : num; }b = readByte(); } }
        boolean isSpaceChar(int c) {
            return (!(c >= 33 && c <= 126));
        }
        int skip() { int b;while ((b = readByte()) != -1 && isSpaceChar(b)) ;return b; }
        float nf() {return Float.parseFloat(ns());}
        double nd() {return Double.parseDouble(ns());}
        char nc() {return (char) skip();}
    }

}


import java.util.Scanner;

public class cowAndMessage_div1And2_621 {

	public static void main(String[] args) {
		Scanner scn=new Scanner(System.in);
		String str=scn.nextLine();
		int[]arr=new int[26];
		for(int i=0;i<str.length();i++) {
			arr[str.charAt(i)-'a']++;
		}
		int idx=0,max1=0;
		for(int i=0;i<26;i++) {
			if(arr[i]>max1) {
				idx=i;
				max1=arr[i];
			}
		}
		arr[idx]=0;
		int max2=0;
		for(int i=0;i<26;i++) {
			if(arr[i]>max2) {
				idx=i;
				max2=arr[i];
			}
		}
		if(max1==0 || max2==0)
			System.out.println(Math.max(max1,max2));
		else
		System.out.println(max1*max2);
	}

}


import java.util.Scanner;

public class cowAndMessage_div1And2_621 {

	public static void main(String[] args) {
		Scanner scn=new Scanner(System.in);
		String str=scn.nextLine();

		int[]arr=new int[26];
		int[][]dp=new int[26][26];

		for(int i=0;i<str.length();i++) {
			arr[str.charAt(i)-'a']++;
		}
		int max=0;

		for(int i=0;i<str.length();i++) {
			int ch=str.charAt(i)-'a';
			max=Math.max(max, arr[ch]);
			arr[ch]--;
			for(int j=0;j<26;j++) {
				dp[ch][j]+=arr[j];
				max=Math.max(dp[ch][j],max);
			}
//			System.out.println(dp[0][1]);
		}
		System.out.println(max);
	}

}


import java.util.Scanner;

public class cowAndMessage_div1And2_621 {

	public static void main(String[] args) {
		Scanner scn=new Scanner(System.in);
		String str=scn.nextLine();

		int[]arr=new int[26];
		long[][]dp=new long[26][26];

		for(int i=0;i<str.length();i++) {
			arr[str.charAt(i)-'a']++;
		}
		long max=0;

		for(int i=0;i<str.length();i++) {
			int ch=str.charAt(i)-'a';
			max=Math.max(max, arr[ch]);
			arr[ch]--;
			for(int j=0;j<26;j++) {
				dp[ch][j]+=arr[j]*1L;
				max=Math.max(dp[ch][j],max);
			}
//			System.out.println(dp[0][1]);
		}
		System.out.println(max);
	}

}


//I AM THE CREED
/* //I AM THE CREED
/* package codechef; // don't place package name! */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.*;
public class HelloWorld{
    public static void main(String[] args) throws IOException
    {

        Scanner input = new Scanner(System.in);

        while(input.hasNext()){
            String s=input.next();
            long max=0;
            for(int i=0;i<26;i++){
                for(int j=0;j<26;j++){
                    if(i==j){
                        long c=0;
                        for(int k=0;k<s.length();k++){
                            if(s.charAt(k)==(char)(i+'a')){
                                c++;
                            }
                        }
                        max=Math.max(max, Math.max(c, (c*(c-1))/2));
                        continue;
                    }
                    long prefix=0;
                    long suffix=0;
                    long ct=0;
                    for(int k=0;k<s.length();k++){
                        if(s.charAt(k)==(char)(j+'a')){
                            ct+=(prefix);
                            continue;
                        }
                        if(s.charAt(k)==(char)(i+'a')){
                            prefix++;
                        }
                    }
                    max=Math.max(ct, max);
                }
            }
            System.out.println(max);

        }

    }

}


//I AM THE CREED
/* //I AM THE CREED
/* package codechef; // don't place package name! */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.*;
public class HelloWorld{
    public static void main(String[] args) throws IOException
    {

        Scanner input = new Scanner(System.in);

        while(input.hasNext()){
            String s=input.next();
            int max=0;
            for(int i=0;i<26;i++){
                for(int j=0;j<26;j++){
                    if(i==j){
                        int c=0;
                        for(int k=0;k<s.length();k++){
                            if(s.charAt(k)==(char)(i+'a')){
                                c++;
                            }
                        }
                        max=Math.max(max, Math.max(c, (c*(c-1))/2));
                    }
                    int prefix=0;
                    int suffix=0;
                    int ct=0;
                    for(int k=0;k<s.length();k++){
                        if(s.charAt(k)==(char)(j+'a')){
                            suffix++;
                            ct=(prefix)*(suffix);
                            continue;
                        }
                        if(s.charAt(k)==(char)(i+'a')){
                            prefix++;
                        }
                    }
                    max=Math.max(ct, max);
                }
            }
            System.out.println(max);

        }

    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CowAndMessage {
    public static void main(String[] args) throws IOException{
        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
        String s = r.readLine();
        int n = s.length();
        int[][]array = new int[n + 1][26];
        for(int i = n - 1; i >= 0; i--){
            for(int j = 0; j < 26; j++ )
                array[i][j] = array[i + 1][j];
            array[i][s.charAt(i) % 26]++;
        }

        long max = 0;
        for(int i = 0; i < 26; i++)
            for(int j = 0; j < 26; j++){
                long ans = 0;
                for(int l = 0; l < n; l++)
                    if(s.charAt(l) % 26== i)
                        ans += array[l + 1][j];
                max = Math.max(ans, max);
        }

        for(int i = 0; i < 26; i++)
            max = Math.max(max, array[0][i]);
        System.out.println(max);
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class C {
	public static void main(String []args) throws Exception
	{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String input;
		String str;
		String []splited;
		int q,n,m,t;
		int []arr;int ans=0,d=0,x;
		input=br.readLine();
		splited=input.split(" ");
		str=input;
		long a1[],a2[][];
		a1=new long[26];
		a2=new long[26][26];

			for(int i=0;i<str.length();i++)
			{

				for(int j=0;j<26;j++)
				{
					a2[j][str.charAt(i)-'a']+=a1[j];
				}
				a1[str.charAt(i)-'a']++;
			}
			long max=-1;
			for(int j=0;j<26;j++)
			{

				for(int k=0;k<26;k++)
				{
					if(a2[j][k]>max)
						max=a2[j][k];
				}
			}
			for(int k=0;k<26;k++)
			{
				if(a1[k]>max)
					max=a1[k];
			}
		System.out.println(max);

	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class C {
	public static void main(String []args) throws Exception
	{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String input;
		String str;
		String []splited;
		int q,n,m,t;
		int []arr;int ans=0,d=0,x;
		input=br.readLine();
		splited=input.split(" ");
		str=input;
		int a1[],a2[][];
		a1=new int[26];
		a2=new int[26][26];

			for(int i=0;i<str.length();i++)
			{

				for(int j=0;j<26;j++)
				{
					a2[j][str.charAt(i)-'a']+=a1[j];
				}
				a1[str.charAt(i)-'a']++;
			}
			int max=-1;
			for(int j=0;j<26;j++)
			{

				for(int k=0;k<26;k++)
				{
					if(a2[j][k]>max)
						max=a2[j][k];
				}
			}
			for(int k=0;k<26;k++)
			{
				if(a1[k]>max)
					max=a1[k];
			}
		System.out.println(max);

	}
}