import java.util.*;
import java.util.logging.Level;
import java.io.*;

public class tr0 {
	static PrintWriter out;
	static StringBuilder sb;
	static final double EPS = 1e-9;
	static long mod = 1000000007;
	static int inf = (int) 1e9 + 2;
	static long[] fac;
	static int[] si;
	static ArrayList<Integer> primes;
	static ArrayList<qu>[] ad;
	static ArrayList<qu>[] d;
	static edge[] ed;
	static int[] l, ch;
	static int[] occ;
	static long[][] adjMatrix;
	static Queue<Integer>[] can;
	static String s;
	static int[][] memo, P;
	static int n, k;
	static int[] ans, p, aa, bb, qq;
	static boolean[] t;
	static HashMap<Integer, Integer> pri;
	static TreeMap<qu, Integer> map;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		String s = sc.nextLine();
		long[] a = new long[26];
		for (int i = 0; i < s.length(); i++)
			a[s.charAt(i) - 'a']++;
		long ans = 0;
		for (int i = 0; i < 26; i++)
			ans = Math.max(ans, a[i]);
		HashMap<String, Long> h = new HashMap<>();
		for (int i = 0; i < s.length(); i++) {
			a[s.charAt(i) - 'a']--;
			for (int j = 0; j < 26; j++) {
				String w=""+s.charAt(i)+(char)(j+'a');
				if(a[j]==0)
					continue;
				if(s.charAt(i)-'a'==j) {
					 h.put(w,h.getOrDefault(w, 0l)+a[j]);
				}
				else
                   h.put(w,h.getOrDefault(w, 0l)+a[j]);
			}
			//System.out.println(Arrays.toString(a));
		//	System.out.println(h);
		}
		for(String k:h.keySet())
			ans=Math.max(ans, h.get(k));
		out.print(ans);
		out.flush();
	}

	static class qu implements Comparable<qu> {
		int a;
		int b;
		int w;

		qu(int aa, int bb, int cc) {
			a = aa;
			b = bb;
			w = cc;
		}

		public String toString() {
			return a + " " + b + " " + w;
		}

		public int compareTo(qu o) {
			if (a == o.a)
				return b - o.b;
			return a - o.a;
		}
	}

	static class seg implements Comparable<seg> {
		int a;
		int b;
		int l;
		int r;
		int bit;

		seg(int s, int e, int x, int y, int bi) {
			a = s;
			b = e;
			l = x;
			r = y;
			bit = bi;
		}

		public String toString() {
			return a + " " + b + " " + l + " " + r + " " + bit;
		}

		public int compareTo(seg o) {
			// if(a==o.a)
			return bit - o.bit;
			// return
		}
	}

	static class pair implements Comparable<pair> {
		long to;
		long number;

		pair(long t, long n) {
			number = n;
			to = t;
		}

		public String toString() {
			return to + " " + number;
		}

		@Override
		public int compareTo(pair o) {
			if (o.to < to)
				return 1;
			return -1;
		}

	}

	static long modPow(long a, long e)

	{
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1;
		}
		return res;
	}

	static long inver(long x) {
		long a = x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				res = ((1l * res * a) % mod);
			}
			a = ((1l * a * a) % mod);
			e >>= 1;
		}
		return res % mod;
	}

	static class edge implements Comparable<edge> {
		int from;
		int to;
		int number;

		edge(int f, int t, int n) {
			from = f;
			to = t;
			number = n;
		}

		public String toString() {
			return from + " " + to + " " + number;
		}

		public int compareTo(edge f) {
			return f.number - number;
		}
	}

	static void seive(int N) {
		si = new int[N];
		primes = new ArrayList<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);
		}
	}

	static long fac(int n) {
		if (n == 0)
			return fac[n] = 1;
		if (n == 1)
			return fac[n] = 1;
		long ans = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = ans = (i % mod * ans % mod) % mod;
		return ans % mod;
	}

	static long gcd(long a, long b) {

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

	static class unionfind {
		int[] p;
		int[] size;
		int[] max;
		int num;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];
			max = new int[n];
			for (int i = 0; i < n; i++) {
				p[i] = i;
				max[i] = i;
			}
			Arrays.fill(size, 1);
			num = n;
		}

		int findSet(int v) {
			if (v == p[v])
				return v;

			max[v] = Math.max(max[v], max[p[v]]);

			p[v] = findSet(p[v]);

			max[v] = Math.max(max[v], max[p[v]]);

			return p[v];
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		boolean combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			// System.out.println(num+" ppp");
			num--;
			if (size[a] > size[b]) {
				p[b] = a;
				max[a] = Math.max(max[a], max[b]);
				size[a] += size[b];

			} else {
				p[a] = b;
				max[b] = Math.max(max[a], max[b]);
				size[b] += size[a];
			}
			return false;
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

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

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

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

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

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

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

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.util.*;
import java.util.logging.Level;
import java.io.*;

public class tr0 {
	static PrintWriter out;
	static StringBuilder sb;
	static final double EPS = 1e-9;
	static long mod = 1000000007;
	static int inf = (int) 1e9 + 2;
	static long[] fac;
	static int[] si;
	static ArrayList<Integer> primes;
	static ArrayList<qu>[] ad;
	static ArrayList<qu>[] d;
	static edge[] ed;
	static int[] l, ch;
	static int[] occ;
	static long[][] adjMatrix;
	static Queue<Integer>[] can;
	static String s;
	static int[][] memo, P;
	static int n, k;
	static int[] ans, p, aa, bb, qq;
	static boolean[] t;
	static HashMap<Integer, Integer> pri;
	static TreeMap<qu, Integer> map;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		String s = sc.nextLine();
		long[] a = new long[26];
		for (int i = 0; i < s.length(); i++)
			a[s.charAt(i) - 'a']++;
		long ans = 0;
		for (int i = 0; i < 26; i++)
			ans = Math.max(ans, a[i]);
		HashMap<String, Long> h = new HashMap<>();
		for (int i = 0; i < s.length(); i++) {
			a[s.charAt(i) - 'a']--;
			for (int j = 0; j < 26; j++) {
				String w=""+s.charAt(i)+(char)(j+'a');
				if(a[j]==0)
					continue;
				if(s.charAt(i)-'a'==j) {
					 h.put(w,h.getOrDefault(w, 0l)+a[j]);
				}
				else
                   h.put(w,h.getOrDefault(w, 0l)+a[s.charAt(i)-'a']*a[j]);
			}
			//System.out.println(Arrays.toString(a));
		//	System.out.println(h);
		}
		for(String k:h.keySet())
			ans=Math.max(ans, h.get(k));
		out.print(ans);
		out.flush();
	}

	static class qu implements Comparable<qu> {
		int a;
		int b;
		int w;

		qu(int aa, int bb, int cc) {
			a = aa;
			b = bb;
			w = cc;
		}

		public String toString() {
			return a + " " + b + " " + w;
		}

		public int compareTo(qu o) {
			if (a == o.a)
				return b - o.b;
			return a - o.a;
		}
	}

	static class seg implements Comparable<seg> {
		int a;
		int b;
		int l;
		int r;
		int bit;

		seg(int s, int e, int x, int y, int bi) {
			a = s;
			b = e;
			l = x;
			r = y;
			bit = bi;
		}

		public String toString() {
			return a + " " + b + " " + l + " " + r + " " + bit;
		}

		public int compareTo(seg o) {
			// if(a==o.a)
			return bit - o.bit;
			// return
		}
	}

	static class pair implements Comparable<pair> {
		long to;
		long number;

		pair(long t, long n) {
			number = n;
			to = t;
		}

		public String toString() {
			return to + " " + number;
		}

		@Override
		public int compareTo(pair o) {
			if (o.to < to)
				return 1;
			return -1;
		}

	}

	static long modPow(long a, long e)

	{
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1;
		}
		return res;
	}

	static long inver(long x) {
		long a = x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				res = ((1l * res * a) % mod);
			}
			a = ((1l * a * a) % mod);
			e >>= 1;
		}
		return res % mod;
	}

	static class edge implements Comparable<edge> {
		int from;
		int to;
		int number;

		edge(int f, int t, int n) {
			from = f;
			to = t;
			number = n;
		}

		public String toString() {
			return from + " " + to + " " + number;
		}

		public int compareTo(edge f) {
			return f.number - number;
		}
	}

	static void seive(int N) {
		si = new int[N];
		primes = new ArrayList<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);
		}
	}

	static long fac(int n) {
		if (n == 0)
			return fac[n] = 1;
		if (n == 1)
			return fac[n] = 1;
		long ans = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = ans = (i % mod * ans % mod) % mod;
		return ans % mod;
	}

	static long gcd(long a, long b) {

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

	static class unionfind {
		int[] p;
		int[] size;
		int[] max;
		int num;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];
			max = new int[n];
			for (int i = 0; i < n; i++) {
				p[i] = i;
				max[i] = i;
			}
			Arrays.fill(size, 1);
			num = n;
		}

		int findSet(int v) {
			if (v == p[v])
				return v;

			max[v] = Math.max(max[v], max[p[v]]);

			p[v] = findSet(p[v]);

			max[v] = Math.max(max[v], max[p[v]]);

			return p[v];
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		boolean combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			// System.out.println(num+" ppp");
			num--;
			if (size[a] > size[b]) {
				p[b] = a;
				max[a] = Math.max(max[a], max[b]);
				size[a] += size[b];

			} else {
				p[a] = b;
				max[b] = Math.max(max[a], max[b]);
				size[b] += size[a];
			}
			return false;
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

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

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

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

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

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

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

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.util.*;
import java.util.logging.Level;
import java.io.*;

public class tr0 {
	static PrintWriter out;
	static StringBuilder sb;
	static final double EPS = 1e-9;
	static long mod = 1000000007;
	static int inf = (int) 1e9 + 2;
	static long[] fac;
	static int[] si;
	static ArrayList<Integer> primes;
	static ArrayList<qu>[] ad;
	static ArrayList<qu>[] d;
	static edge[] ed;
	static int[] l, ch;
	static int[] occ;
	static long[][] adjMatrix;
	static Queue<Integer>[] can;
	static String s;
	static int[][] memo, P;
	static int n, k;
	static int[] ans, p, aa, bb, qq;
	static boolean[] t;
	static HashMap<Integer, Integer> pri;
	static TreeMap<qu, Integer> map;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
	    String s=sc.nextLine();
	    long []a=new long[26];
	    for(int i=0;i<s.length();i++)
	    	a[s.charAt(i)-'a']++;
	    long ans=0;
	    for(int i=0;i<26;i++)
	    	ans=Math.max(ans, a[i]);
	    for(int i=0;i<26;i++)
	    	for(int j=i+1;j<26;j++)
	    		ans=Math.max(ans,a[i]*a[j]);
	    out.print(ans);
		out.flush();
	}
	static class qu implements Comparable<qu> {
		int a;
		int b;
		int w;

		qu(int aa, int bb, int cc) {
			a = aa;
			b = bb;
			w = cc;
		}

		public String toString() {
			return a + " " + b + " " + w;
		}

		public int compareTo(qu o) {
			if (a == o.a)
				return b - o.b;
			return a - o.a;
		}
	}

	static class seg implements Comparable<seg> {
		int a;
		int b;
		int l;
		int r;
		int bit;

		seg(int s, int e, int x, int y, int bi) {
			a = s;
			b = e;
			l = x;
			r = y;
			bit = bi;
		}

		public String toString() {
			return a + " " + b + " " + l + " " + r + " " + bit;
		}

		public int compareTo(seg o) {
			// if(a==o.a)
			return bit - o.bit;
			// return
		}
	}

	static class pair implements Comparable<pair> {
		long to;
		long number;

		pair(long t, long n) {
			number = n;
			to = t;
		}

		public String toString() {
			return to + " " + number;
		}

		@Override
		public int compareTo(pair o) {
			if (o.to < to)
				return 1;
			return -1;
		}

	}

	static long modPow(long a, long e)

	{
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1;
		}
		return res;
	}

	static long inver(long x) {
		long a = x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				res = ((1l * res * a) % mod);
			}
			a = ((1l * a * a) % mod);
			e >>= 1;
		}
		return res % mod;
	}

	static class edge implements Comparable<edge> {
		int from;
		int to;
		int number;

		edge(int f, int t, int n) {
			from = f;
			to = t;
			number = n;
		}

		public String toString() {
			return from + " " + to + " " + number;
		}

		public int compareTo(edge f) {
			return f.number - number;
		}
	}

	static void seive(int N) {
		si = new int[N];
		primes = new ArrayList<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);
		}
	}

	static long fac(int n) {
		if (n == 0)
			return fac[n] = 1;
		if (n == 1)
			return fac[n] = 1;
		long ans = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = ans = (i % mod * ans % mod) % mod;
		return ans % mod;
	}

	static long gcd(long a, long b) {

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

	static class unionfind {
		int[] p;
		int[] size;
		int[] max;
		int num;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];
			max = new int[n];
			for (int i = 0; i < n; i++) {
				p[i] = i;
				max[i] = i;
			}
			Arrays.fill(size, 1);
			num = n;
		}

		int findSet(int v) {
			if (v == p[v])
				return v;

			max[v] = Math.max(max[v], max[p[v]]);

			p[v] = findSet(p[v]);

			max[v] = Math.max(max[v], max[p[v]]);

			return p[v];
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		boolean combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			// System.out.println(num+" ppp");
			num--;
			if (size[a] > size[b]) {
				p[b] = a;
				max[a] = Math.max(max[a], max[b]);
				size[a] += size[b];

			} else {
				p[a] = b;
				max[b] = Math.max(max[a], max[b]);
				size[b] += size[a];
			}
			return false;
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

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

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

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

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

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

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

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import sun.awt.image.ImageWatched;

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Scanner_ {
    //global methods
    static class MyReader {
        BufferedReader br;
        StringTokenizer st;

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

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

        int ni() {
            return Integer.parseInt(ne());
        }

        long nl() {
            return Long.parseLong(ne());
        }

        double nd() {
            return Double.parseDouble(ne());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static void main(String[] args) {
        new Thread(null, null, "Rahsut", 1 << 25) {
            public void run() {
                try {
                    Freak();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static long modPow(long x, long p, long m) {
        if (p == 0)
            return 1;
        if (p % 2 == 0)
            return modPow((x * x) % m, p >> 1, m) % m;
        return x * (modPow(x, p - 1, m) % m) % m;
    }
    static long mul(long a, long b, long m) {
        a %= m;
        b %= m;
        return (a * b) % m;
    }
    static long gcd(long a,long b) {
        if(b%a==0)
            return a;
        return gcd(b%a,a);
    }
    static long lcm(long a, long b) {
        a/=gcd(a,b);
        return a*b;
    }
    public static class Pair implements Comparable<Pair> {
        long x, y;
        Pair(long x, long y) {
            this.x = x;
            this.y = y;
        }

        public int compareTo(Pair o) {
            if (x != o.x)
                return (int)x - (int)o.x;
            return (int)y - (int)o.y;
        }

        public String toString() {
            return x + " " + y;
        }
    }

    //global variables
    static MyReader sc = new MyReader();
    static StringBuilder sb = new StringBuilder();
    static PrintWriter pw = new PrintWriter(System.out, true);
    static int dir1[][]= {{1,0},{-1,0},{0,1},{0,-1}},n,q,t;
    static int dir2[][] ={{1,-1},{-1,1},{1,1},{-1,-1}};
    static int dp[][], mod = (int)1e9 + 7;
    static char arr[];
    static void Freak() throws IOException {
        arr = sc.ne().toCharArray();
        n = arr.length;
        int pref[][] = new int[n][26];
        int suf[][]= new int[n][26];
        pref[0][arr[0]-'a']=1;
        for(int i =1;i<n;i++) {
            for(int j = 0;j<26;j++) {
                pref[i][j] = pref[i-1][j];
            }
            pref[i][arr[i]-'a']++;
        }
        suf[n-1][arr[n-1]-'a']++;
        for(int i = n-2;i>=0;i--) {
            for(int j =0;j<26;j++)
                suf[i][j]=suf[i+1][j];
            suf[i][arr[i]-'a']++;
        }
        long ans = 0;
        for(int i =0;i<n;i++) {
            int k = arr[i]-'a';
            ans = max(ans,pref[i][k]);
            if(i+1<n) {
                for (int j = 0; j < 26; j++) {
                    ans = max(ans, pref[i][k] * suf[i + 1][j]);
                }
            }
        }
        sb.append(ans);

        pw.println(sb);
        pw.flush();
        pw.close();
    }
}


import sun.awt.image.ImageWatched;

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Scanner_ {
    //global methods
    static class MyReader {
        BufferedReader br;
        StringTokenizer st;

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

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

        int ni() {
            return Integer.parseInt(ne());
        }

        long nl() {
            return Long.parseLong(ne());
        }

        double nd() {
            return Double.parseDouble(ne());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static void main(String[] args) {
        new Thread(null, null, "Rahsut", 1 << 25) {
            public void run() {
                try {
                    Freak();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static long modPow(long x, long p, long m) {
        if (p == 0)
            return 1;
        if (p % 2 == 0)
            return modPow((x * x) % m, p >> 1, m) % m;
        return x * (modPow(x, p - 1, m) % m) % m;
    }
    static long mul(long a, long b, long m) {
        a %= m;
        b %= m;
        return (a * b) % m;
    }
    static long gcd(long a,long b) {
        if(b%a==0)
            return a;
        return gcd(b%a,a);
    }
    static long lcm(long a, long b) {
        a/=gcd(a,b);
        return a*b;
    }
    public static class Pair implements Comparable<Pair> {
        long x, y;
        Pair(long x, long y) {
            this.x = x;
            this.y = y;
        }

        public int compareTo(Pair o) {
            if (x != o.x)
                return (int)x - (int)o.x;
            return (int)y - (int)o.y;
        }

        public String toString() {
            return x + " " + y;
        }
    }

    //global variables
    static MyReader sc = new MyReader();
    static StringBuilder sb = new StringBuilder();
    static PrintWriter pw = new PrintWriter(System.out, true);
    static int dir1[][]= {{1,0},{-1,0},{0,1},{0,-1}},n,q,t;
    static int dir2[][] ={{1,-1},{-1,1},{1,1},{-1,-1}};
    static int dp[][], mod = (int)1e9 + 7;
    static char arr[];
    static long ans =1;
    static void Freak() throws IOException {
        arr = sc.ne().toCharArray();
        n = arr.length;
        long pref[][] = new long[n][26];
        long suf[][]= new long[n][26];
        pref[0][arr[0]-'a']=1;
        for(int i =1;i<n;i++) {
            for(int j = 0;j<26;j++) {
                pref[i][j] = pref[i-1][j];
            }
            pref[i][arr[i]-'a']++;
        }
        suf[n-1][arr[n-1]-'a']=1;
        for(int i = n-2;i>=0;i--) {
            for(int j =0;j<26;j++)
                suf[i][j]=suf[i+1][j];
            suf[i][arr[i]-'a']++;
        }
        HashMap<String,Long> map = new HashMap<>();
        for(int i =0;i<n;i++) {
            int k = arr[i]-'a';
            put(map,""+arr[i],1);
            if(i+1<n) {
                for (int j = 0; j < 26; j++) {
                    char x = (char)(j+'a');
                    if(suf[i+1][j]>0)
                        put(map,""+arr[i]+x,suf[i+1][j]);
                }
            }
        }
//        System.out.println(map);
        sb.append(ans);

        pw.println(sb);
        pw.flush();
        pw.close();
    }
    static void put(HashMap<String,Long> map,String key,long add) {
        ans = max(ans,add);
        if(map.containsKey(key)) {
            long val = map.get(key)+add;
            map.put(key, val );
            ans = max(ans,val);
        }else
            map.put(key,add);
    }
}


import sun.awt.image.ImageWatched;

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Scanner_ {
    //global methods
    static class MyReader {
        BufferedReader br;
        StringTokenizer st;

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

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

        int ni() {
            return Integer.parseInt(ne());
        }

        long nl() {
            return Long.parseLong(ne());
        }

        double nd() {
            return Double.parseDouble(ne());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static void main(String[] args) {
        new Thread(null, null, "Rahsut", 1 << 25) {
            public void run() {
                try {
                    Freak();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static long modPow(long x, long p, long m) {
        if (p == 0)
            return 1;
        if (p % 2 == 0)
            return modPow((x * x) % m, p >> 1, m) % m;
        return x * (modPow(x, p - 1, m) % m) % m;
    }
    static long mul(long a, long b, long m) {
        a %= m;
        b %= m;
        return (a * b) % m;
    }
    static long gcd(long a,long b) {
        if(b%a==0)
            return a;
        return gcd(b%a,a);
    }
    static long lcm(long a, long b) {
        a/=gcd(a,b);
        return a*b;
    }
    public static class Pair implements Comparable<Pair> {
        long x, y;
        Pair(long x, long y) {
            this.x = x;
            this.y = y;
        }

        public int compareTo(Pair o) {
            if (x != o.x)
                return (int)x - (int)o.x;
            return (int)y - (int)o.y;
        }

        public String toString() {
            return x + " " + y;
        }
    }

    //global variables
    static MyReader sc = new MyReader();
    static StringBuilder sb = new StringBuilder();
    static PrintWriter pw = new PrintWriter(System.out, true);
    static int dir1[][]= {{1,0},{-1,0},{0,1},{0,-1}},n,q,t;
    static int dir2[][] ={{1,-1},{-1,1},{1,1},{-1,-1}};
    static int dp[][], mod = (int)1e9 + 7,ans =1;
    static char arr[];
    static void Freak() throws IOException {
        arr = sc.ne().toCharArray();
        n = arr.length;
        int pref[][] = new int[n][26];
        int suf[][]= new int[n][26];
        pref[0][arr[0]-'a']=1;
        for(int i =1;i<n;i++) {
            for(int j = 0;j<26;j++) {
                pref[i][j] = pref[i-1][j];
            }
            pref[i][arr[i]-'a']++;
        }
        suf[n-1][arr[n-1]-'a']++;
        for(int i = n-2;i>=0;i--) {
            for(int j =0;j<26;j++)
                suf[i][j]=suf[i+1][j];
            suf[i][arr[i]-'a']++;
        }
        HashMap<String,Integer> map = new HashMap<>();
        for(int i =0;i<n;i++) {
            int k = arr[i]-'a';
            put(map,""+arr[i],1);
            if(i+1<n) {
                for (int j = 0; j < 26; j++) {
                    char x = (char)(j+'a');
                    if(suf[i+1][j]>0)
                        put(map,""+arr[i]+x,suf[i+1][j]);
                }
            }
        }
//        System.out.println(map);
        sb.append(ans);

        pw.println(sb);
        pw.flush();
        pw.close();
    }
    static void put(HashMap<String,Integer> map,String key,int add) {
        ans = max(ans,add);
        if(map.containsKey(key)) {
            int val = map.get(key)+add;
            map.put(key, val );
            ans = max(ans,val);
        }else
            map.put(key,add);
    }
}


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

public class Solution {
    public static void main(String[] args) throws Exception {
        FastReader sc = new FastReader();
        char s[]=sc.next().toCharArray();
        int n=s.length;
        int cnt[]=new int[26];
        int dp[][]=new int[n][26];
        long max=0;
        for (int i=0;i<n;i++){
            cnt[s[i]-'a']++;
            dp[i][s[i]-'a']++;
            max=Math.max(max,cnt[s[i]-'a']);
        }
        for (int i=n-2;i>=0;i--){
            for (int j=0;j<26;j++){
                dp[i][j]+=dp[i+1][j];
            }
        }
        for (int x=0;x<26;x++){
            for (int y=0;y<26;y++){
                char a=(char) ('a'+x),b=(char) ('a'+y);
                long ans=0;
                for (int i=0;i<n-1;i++){
                    if (s[i]==a){
                        ans+=dp[i+1][b-'a'];
                    }
                }
                max=Math.max(ans,max);
            }
        }
        System.out.println(max);

    }

    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;
        }
    }
}


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

public class Solution {
    public static void main(String[] args) throws Exception {
        FastReader sc = new FastReader();
        char s[]=sc.next().toCharArray();
        int n=s.length;
        int cnt[]=new int[26];
        int dp[][]=new int[n][26];
        int max=0;
        for (int i=0;i<n;i++){
            cnt[s[i]-'a']++;
            dp[i][s[i]-'a']++;
            max=Math.max(max,cnt[s[i]-'a']);
        }
        for (int i=n-2;i>=0;i--){
            for (int j=0;j<26;j++){
                dp[i][j]+=dp[i+1][j];
            }
        }
        for (int x=0;x<26;x++){
            for (int y=0;y<26;y++){
                char a=(char) ('a'+x),b=(char) ('a'+y);
                int ans=0;
                for (int i=0;i<n-1;i++){
                    if (s[i]==a){
                        ans+=dp[i+1][b-'a'];
                    }
                }
                max=Math.max(ans,max);
            }
        }
        System.out.println(max);

    }

    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;
        }
    }
}


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

public class Main {
    static int i,j,k,n,m,t,s,a,b,c,ans=0;
    static String str;
    static char ch;

    public static void main(String[] args) {

        FastScanner fs = new FastScanner();

        str = fs.next();

        n =str.length();

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

        int [] sum = new int[26];

        int [][] ansArr = new int[26][26];

        for(i=0;i<n;i++){
            ch = str.charAt(i);

            sum[ch-97]++;

            for(j=0;j<26;j++){
                if(i==0)
                    arr[i][j]=0;
                else
                    arr[i][j]= arr[i-1][j];
            }

            arr[i][ch-97]++;
        }

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

        for(i=0;i<n;i++){

            int k = str.charAt(i) -97;

            for(j=0;j<26;j++){
                if(k!=j){
                    ansArr[k][j]+=(sum[j]-arr[i][j]);
                }
            }
        }

        for(i=0;i<26;i++){
            for(j=0;j<26;j++){
                ans = Math.max(ans,ansArr[i][j]);
            }
        }

        System.out.println(ans);

    }

    static void sort(int[] a) {
        ArrayList<Integer> l=new ArrayList<>();
        for (int i:a) l.add(i);
        Collections.sort(l);
        for (int i=0; i<a.length; i++) a[i]=l.get(i);
    }

    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        String next() {
            while (!st.hasMoreTokens())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }

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

        int[] readArray(int n) {
            int[] a=new int[n];
            for (int i=0; i<n; i++) a[i]=nextInt();
            return a;
        }
        long nextLong() {
            return Long.parseLong(next());
        }
    }

    //To be used with priority queues.
    static class State implements Comparable<State> {
        int l, r;
        int len;
        public State(int l, int r) {
            this.l=l;
            this.r=r;
            this.len=r-l+1;
        }

        public int compareTo(State o) {
            if (len!=o.len) {
                return -Integer.compare(len, o.len);
            }
            else {
                return Integer.compare(l, o.l);
            }
        }
    }

}


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

public class Main {
    static int i,j,k,n,m,t,s,a,b,c;
    static String str;
    static char ch;

    public static void main(String[] args) {

        FastScanner fs = new FastScanner();

        str = fs.next();

        n =str.length();

        long ans = 0;

        long [][] arr = new long[n][26];

        long [] sum = new long[26];

        long [][] ansArr = new long[26][26];

        for(i=0;i<n;i++){
            ch = str.charAt(i);

            sum[ch-97]++;

            for(j=0;j<26;j++){
                if(i==0)
                    arr[i][j]=0;
                else
                    arr[i][j]= arr[i-1][j];
            }

            arr[i][ch-97]++;
        }

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

        for(i=0;i<n;i++){

            int k = str.charAt(i) -97;

            for(j=0;j<26;j++){
                ansArr[k][j]+=(sum[j]-arr[i][j]);
            }
        }

        for(i=0;i<26;i++){
            for(j=0;j<26;j++){
                ans = Math.max(ans,ansArr[i][j]);
            }
        }

        System.out.println(ans);

    }

    static void sort(int[] a) {
        ArrayList<Integer> l=new ArrayList<>();
        for (int i:a) l.add(i);
        Collections.sort(l);
        for (int i=0; i<a.length; i++) a[i]=l.get(i);
    }

    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        String next() {
            while (!st.hasMoreTokens())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }

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

        int[] readArray(int n) {
            int[] a=new int[n];
            for (int i=0; i<n; i++) a[i]=nextInt();
            return a;
        }
        long nextLong() {
            return Long.parseLong(next());
        }
    }

    //To be used with priority queues.
    static class State implements Comparable<State> {
        int l, r;
        int len;
        public State(int l, int r) {
            this.l=l;
            this.r=r;
            this.len=r-l+1;
        }

        public int compareTo(State o) {
            if (len!=o.len) {
                return -Integer.compare(len, o.len);
            }
            else {
                return Integer.compare(l, o.l);
            }
        }
    }

}


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

public class Main {
    static int i,j,k,n,m,t,s,a,b,c;
    static String str;
    static char ch;

    public static void main(String[] args) {

        FastScanner fs = new FastScanner();

        str = fs.next();

        n =str.length();

        long ans = 0;

        long [][] arr = new long[n][26];

        long [] sum = new long[26];

        long [][] ansArr = new long[26][26];

        for(i=0;i<n;i++){
            ch = str.charAt(i);

            sum[ch-97]++;

            for(j=0;j<26;j++){
                if(i==0)
                    arr[i][j]=0;
                else
                    arr[i][j]= arr[i-1][j];
            }

            arr[i][ch-97]++;
        }

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

        for(i=0;i<n;i++){

            int k = str.charAt(i) -97;

            for(j=0;j<26;j++){
                if(k!=j){
                    ansArr[k][j]+=(sum[j]-arr[i][j]);
                }
            }
        }

        for(i=0;i<26;i++){
            for(j=0;j<26;j++){
                ans = Math.max(ans,ansArr[i][j]);
            }
        }

        System.out.println(ans);

    }

    static void sort(int[] a) {
        ArrayList<Integer> l=new ArrayList<>();
        for (int i:a) l.add(i);
        Collections.sort(l);
        for (int i=0; i<a.length; i++) a[i]=l.get(i);
    }

    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        String next() {
            while (!st.hasMoreTokens())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }

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

        int[] readArray(int n) {
            int[] a=new int[n];
            for (int i=0; i<n; i++) a[i]=nextInt();
            return a;
        }
        long nextLong() {
            return Long.parseLong(next());
        }
    }

    //To be used with priority queues.
    static class State implements Comparable<State> {
        int l, r;
        int len;
        public State(int l, int r) {
            this.l=l;
            this.r=r;
            this.len=r-l+1;
        }

        public int compareTo(State o) {
            if (len!=o.len) {
                return -Integer.compare(len, o.len);
            }
            else {
                return Integer.compare(l, o.l);
            }
        }
    }

}


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

public class MainClass
{
    public static void main(String[] args)throws IOException
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s = in.readLine();
        int n = s.length();
        int[][] dp = new int[26][n + 1];
        for (int i=n - 1;i>=0;i--)
        {
            int x = s.charAt(i) - 'a';
            for (int j=0;j<26;j++)
                dp[j][i] += dp[j][i + 1];
            dp[x][i] ++;
        }
        long max = 0L;
        for (int i=0;i<26;i++) max = Math.max(max, dp[i][0]);
        for (int i=0;i<26;i++)
        {
            for (int j=0;j<26;j++)
            {
                long count = 0L;
                for (int z=0;z<n;z++)
                {
                    int x1 = s.charAt(z) - 'a';
                    if (x1 == i)
                    {
                        count += dp[j][z];
                        if (x1 == j)
                        {
                            count--;
                        }
                    }
                }
                max = Math.max(count, max);
            }
        }
        System.out.println(max);
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


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

public class MainClass
{
    public static void main(String[] args)throws IOException
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s = in.readLine();
        int n = s.length();
        int[][] dp = new int[26][n + 1];
        for (int i=n - 1;i>=0;i--)
        {
            int x = s.charAt(i) - 'a';
            for (int j=0;j<26;j++)
                dp[j][i] += dp[j][i + 1];
            dp[x][i] ++;
        }
        long max = 0L;
        for (int i=0;i<26;i++) max = Math.max(max, dp[i][0]);
        for (int i=0;i<26;i++)
        {
            for (int j=0;j<26;j++)
            {
                long count = 0L;
                for (int z=0;z<n;z++)
                {
                    int x1 = s.charAt(z) - 'a';
                    if (x1 == i)
                    {
                        count += dp[j][z];
                    }
                    if (x1 == j)
                    {
                        count--;
                    }
                }
                max = Math.max(count, max);
            }
        }
        System.out.println(max);
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


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

public class MainClass
{
    public static void main(String[] args)throws IOException
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s = in.readLine();
        int n = s.length();
        int[][] dp = new int[26][n + 1];
        for (int i=n - 1;i>=0;i--)
        {
            int x = s.charAt(i) - 'a';
            for (int j=0;j<26;j++)
                dp[j][i] += dp[j][i + 1];
            dp[x][i] ++;
        }
        long max = Long.MIN_VALUE;
        for (int i=0;i<26;i++) max = Math.max(max, dp[i][0]);
        for (int i=0;i<26;i++)
        {
            for (int j=0;j<26;j++)
            {
                long count = 0L;
                if (i != j)
                {
                    for (int z=0;z<n;z++)
                    {
                        int x1 = s.charAt(z) - 'a';
                        if (x1 == i)
                        {
                            count += dp[j][z];
                        }
                    }
                }
                max = Math.max(count, max);
            }
        }
        System.out.println(max);
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


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

public class TestClass {

    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        ArrayList<String> arr = new ArrayList<>();
        for(char ch = 'a'; ch<='z'; ch++){
            for(char ch1 = 'a'; ch1<='z'; ch1++){
                if(ch != ch1)
                    arr.add(Character.toString(ch) + Character.toString(ch1));
            }
        }
        long maxCnt = 0;
        for(String in: arr){
            char a = in.charAt(0);
            char b = in.charAt(1);
            int cntab = 0;
            int cnta = 0;
            for(int i=0;i<s.length();i++){
                if(s.charAt(i) == a){
                    cnta++;
                }
                else if(s.charAt(i) == b){
                    cntab += cnta;
                }
            }
            maxCnt = Long.max(maxCnt, cntab);
        }

        long[] charCnt = new long[26];
        for(int i=0;i<s.length();i++){
            charCnt[s.charAt(i)-'a']++;
        }

        for(int i=0;i<26;i++){
            long n = charCnt[i];
            maxCnt = Long.max(maxCnt, n);
            maxCnt = Long.max(maxCnt, ((n*(n-1))/2));
        }

        System.out.println(maxCnt);
    }
}


import java.util.*;

public class TestClass {

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        ArrayList<String> arr = new ArrayList<>();
        for(char ch = 'a'; ch<='z'; ch++){
            for(char ch1 = 'a'; ch1<='z'; ch1++){
                if(ch != ch1)
                    arr.add(Character.toString(ch) + Character.toString(ch1));
            }
        }

        long maxCnt = 0;
        for(String in: arr){
            char a = in.charAt(0);
            char b = in.charAt(1);
            long cntab = 0;
            long cnta = 0;
            for(int i=0;i<s.length();i++){
                if(s.charAt(i) == a){
                    cnta++;
                }
                else if(s.charAt(i) == b){
                    cntab += cnta;
                }
            }
            maxCnt = Long.max(maxCnt, cntab);
        }

        long[] charCnt = new long[26];
        for(int i=0;i<s.length();i++){
            charCnt[s.charAt(i)-'a']++;
        }

        for(int i=0;i<26;i++){
            long n = charCnt[i];
            maxCnt = Long.max(maxCnt, n);
            maxCnt = Long.max(maxCnt, ((n*(n-1))/2));
        }

        System.out.println(maxCnt);
    }
}


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

public class TestClass {

    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        ArrayList<String> arr = new ArrayList<>();
        for(char ch = 'a'; ch<='z'; ch++){
            for(char ch1 = 'a'; ch1<='z'; ch1++){
                if(ch != ch1)
                    arr.add(Character.toString(ch) + Character.toString(ch1));
            }
        }
        long maxCnt = 0;
        for(String in: arr){
            char a = in.charAt(0);
            char b = in.charAt(1);
            int cntab = 0;
            int cnta = 0;
            for(int i=0;i<s.length();i++){
                if(s.charAt(i) == a){
                    cnta++;
                }
                else if(s.charAt(i) == b){
                    cntab += cnta;
                }
            }
            maxCnt = Long.max(maxCnt, cntab);
        }

        int[] charCnt = new int[26];
        for(int i=0;i<s.length();i++){
            charCnt[s.charAt(i)-'a']++;
        }

        for(int i=0;i<26;i++){
            int n = charCnt[i];
            maxCnt = Long.max(maxCnt, n);
            maxCnt = Long.max(maxCnt, ((n*(n-1))/2));
        }

        System.out.println(maxCnt);
    }
}


import java.util.*;
   import java.io.*;
   public class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
             else if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           if(i==j)
           {
             count2=(count1*(count1-1))/2;
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
    public class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           long count1=0;
           long count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
            else  if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           if(i==j)
           {
             count2=(count1*(count1-1))/2;
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
    public class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
             else if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
  public  class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
             else if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           if(i==j)
           {
             count2=(count1*(count1-1))/2;
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
   public class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if(s[k]-'a'==pair2)
            {
              count2+=count1;
            }
             if((s[k]-'a')==pair1)
             {
               count1++;
             }

           }

           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
    public class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {

             if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
           }

           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
 public   class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
             else if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           if(i==j)
           {
             count2=(count1*(count1-1));
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
   import java.io.*;
  public  class Solution {
     static ArrayList<Integer> graph[];
     static boolean vis[];
     static int seive[]=new int[1000001];
     static int dis[]=new int[1000001];
     static int subtree[]=new int[1000001];
     static int N =1000001;
     static HashSet<String> hm=new HashSet<>();
   static HashSet<String> hm1=new HashSet<>();
     static int time=0;
     public static void main(String[] args) {
       Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
       String str=sc.next();
       char s[]=str.toCharArray();
       int n=str.length();
       int map[]=new int[26];
       long ans=0;
       for( int i=0;i<n;i++)
       {
         map[s[i]-'a']++;
         ans=Math.max(ans, map[s[i]-'a']);
       }
       for(int i=0;i<26;i++)
       {
         for( int j=0;j<26;j++)
         {
           int pair1=i;
           int pair2=j;
           int count1=0;
           int count2=0;
           for( int k=0;k<n;k++)
           {
             if((s[k]-'a')==pair1)
             {
               count1++;
             }
             else if(s[k]-'a'==pair2)
             {
               count2+=count1;
             }
           }
           if(i==j)
           {
             count2=(count1*(count1+1))/2;
           }
           ans=Math.max(ans, Math.max(count1, count2));
         }
       }
       System.out.println(ans);
     }

  //******************************************************************

public static void func(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm.add(str);
    return;
  }
  if(bal==1)
  {
    func(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func(a, index+1, str+"L",bal+1);
  }
  else
  {
    func(a, index+1, str+"R",bal-1);
    func(a, index+1, str+"L",bal+1);
  }

}
public static void func1(int a[], int index,String str, int bal)
{
  if(index==a.length-1)
  {
    hm1.add(str);
    return;
  }
  if(bal==1)
  {
    func1(a, index+1, str+"R",bal-1);
  }
  else if(bal==-1)
  {
    func1(a, index+1, str+"L",bal+1);
  }
  else
  {
    func1(a, index+1, str+"R",bal-1);
    func1(a, index+1, str+"L",bal+1);
  }

}
public static long power(long x, long y, long p)
   {
       // Initialize result
       long res = 1;

       // Update x if it is more
       // than or equal to p
       x = x % p;

       while (y > 0)
       {
           // If y is odd, multiply x
           // with result
           if((y & 1)==1)
               res = (res * x) % p;

           // y must be even now
           // y = y / 2
           y = y >> 1;
           x = (x * x) % p;
       }
       return res;
   }

}


import java.util.*;
public class MyClass {
    public static void main(String args[]) {
        Scanner sc=new Scanner(System.in);
        char a[]=sc.next().toCharArray();
        int l_pre[][]=new int[a.length+1][26];
        long max=1;
        for(int i=1;i<=a.length;i++)
        {
            l_pre[i][a[i-1]-'a']++;
            for(int j=0;j<26;j++)
            {
                l_pre[i][j]=l_pre[i-1][j]+l_pre[i][j];
                max=Math.max(l_pre[i][j],max);
                //System.out.print(l_pre[i][j]+" ");
            }
            //System.out.println();
        }
        HashMap<String,Long> hm=new HashMap<>();
        String temp="";
        long val=0;
        for(int i=2;i<=a.length;i++)
        {
            temp="";
            for(int j=0;j<26;j++)
            {
                val=0;
                if(l_pre[i-1][j]>0)
                {
                    val=l_pre[i-1][j];
                    temp=(char)(j+97)+"";
                    temp=temp+a[i-1];
                    hm.put(temp,hm.getOrDefault(temp,0L)+val);
                    if(hm.get(temp)>max)
                    {
                        max=hm.get(temp);
                    }
                }
            }
        }
        System.out.println(max);
    }
}


import java.util.*;
public class MyClass {
    public static void main(String args[]) {
        Scanner sc=new Scanner(System.in);
        char a[]=sc.next().toCharArray();
        int l_pre[][]=new int[a.length+1][26];
        int r_pre[][]=new int[a.length+1][26];
        int max=1;
        for(int i=1;i<=a.length;i++)
        {
            l_pre[i][a[i-1]-'a']++;
            for(int j=0;j<26;j++)
            {
                l_pre[i][j]=l_pre[i-1][j]+l_pre[i][j];
                max=Math.max(l_pre[i][j],max);
            }
        }
        for(int i=a.length;i>=1;i--)
        {
            r_pre[i][a[i-1]-'a']++;
            if(i!=a.length)
            {
                for(int j=0;j<26;j++)
                {
                    r_pre[i][j]=r_pre[i+1][j]+r_pre[i][j];
                    max=Math.max(r_pre[i][j],max);
                }
            }
        }
        int l_max=0,r_max=0;
        for(int i=1;i<=a.length-1;i++)
        {
            l_max=0;r_max=0;
            for(int j=0;j<26;j++)
            {
                l_max=Math.max(l_max,l_pre[i][j]);
            }
            for(int j=0;j<26;j++)
            {
                r_max=Math.max(r_max,l_pre[a.length-i][j]);
            }
            max=Math.max(max,l_max*r_max);
        }
        System.out.println(max);
    }
}


import java.util.*;
public class MyClass {
    public static void main(String args[]) {
        Scanner sc=new Scanner(System.in);
        char a[]=sc.next().toCharArray();
        int l_pre[][]=new int[a.length+1][26];
        int max=1;
        for(int i=1;i<=a.length;i++)
        {
            l_pre[i][a[i-1]-'a']++;
            for(int j=0;j<26;j++)
            {
                l_pre[i][j]=l_pre[i-1][j]+l_pre[i][j];
                max=Math.max(l_pre[i][j],max);
                //System.out.print(l_pre[i][j]+" ");
            }
            //System.out.println();
        }
        HashMap<String,Integer> hm=new HashMap<>();
        String temp="";
        int val=0;
        for(int i=2;i<=a.length;i++)
        {
            temp="";
            for(int j=0;j<26;j++)
            {
                val=0;
                if(l_pre[i-1][j]>0)
                {
                    val=l_pre[i-1][j];
                    temp=(char)(j+97)+"";
                    temp=temp+a[i-1];
                    hm.put(temp,hm.getOrDefault(temp,0)+val);
                    if(hm.get(temp)>max)
                    {
                        max=hm.get(temp);
                    }
                }
            }
        }
        System.out.println(max);
    }
}


/*****Author: Satyajeet Singh, Delhi Technological University************************************/
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.lang.*;
    import java.math.*;
public class Main{
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static long factorial[],invFactorial[];
    static ArrayList<Integer> graph[];
    static int pptr=0;
    static String st[];
/****************************************Solutions Begins***************************************/
    public static void main(String args[]) throws Exception{
        nl();
        String str=ps();
        int n=str.length();
        HashMap<String,Long> map=new HashMap<>();
        long dp[]=new long[26];
        long ans=0;
        for(int i=0;i<n;i++){
            int ch=str.charAt(i)-'a';
            dp[ch]++;
            for(char c='a';c<='z';c++){
                if(c==str.charAt(i)){
                    dp[ch]--;
                }
                String s=c+""+str.charAt(i);
                map.put(s,map.getOrDefault(s,0l)+dp[c-'a']);
                ans=Math.max(ans,map.get(s));
                if(c==str.charAt(i)){
                    dp[ch]++;
                }
            }
           // debug(map);

            ans=Math.max(ans,dp[ch]);
        }
     //   debug(map);
        out.println(ans);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
    static void nl() throws Exception{
        pptr=0;
        st=br.readLine().split(" ");
    }
    static void nls() throws Exception{
        pptr=0;
        st=br.readLine().split("");
    }
    static int pi(){
        return Integer.parseInt(st[pptr++]);
    }
    static long pl(){
        return Long.parseLong(st[pptr++]);
    }
    static double pd(){
        return Double.parseDouble(st[pptr++]);
    }
    static String ps(){
        return st[pptr++];
    }
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000000000");
        out.print(ft.format(d));
    }
/**************************************Bit Manipulation**************************************************/
    static void printMask(long mask){
        System.out.println(Long.toBinaryString(mask));
    }
    static int countBit(long mask){
        int ans=0;
        while(mask!=0){
            mask&=(mask-1);
            ans++;
        }
        return ans;
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new ArrayList[n];
        for(int i=0;i<n;i++){
            graph[i]=new ArrayList<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(b);
    }
    // static void addEdge(int a,int b,int c){
    //     graph[a].add(new Pair(b,c));
    // }
/*********************************************PAIR********************************************************/
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }
        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }
        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }
        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }
/******************************************Long Pair*******************************************************/
    static class Pairl implements Comparable<Pairl> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }
            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }
            public boolean equals(Object o) {
                Pairl other = (Pairl) o;
                return u == other.u && v == other.v;
            }
            public int compareTo(Pairl other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }
            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o){
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c){
        long x=1;
        long y=a%c;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y){
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0){
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}


/*****Author: Satyajeet Singh, Delhi Technological University************************************/
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.lang.*;
    import java.math.*;
public class Main{
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static long factorial[],invFactorial[];
    static ArrayList<Integer> graph[];
    static int pptr=0;
    static String st[];
/****************************************Solutions Begins***************************************/
    public static void main(String args[]) throws Exception{
        nl();
        String str=ps();
        int n=str.length();
        HashMap<String,Long> map=new HashMap<>();
        long dp[]=new long[26];
        long ans=0;
        for(int i=0;i<n;i++){
            int ch=str.charAt(i)-'a';
            for(char c='a';c<='z';c++){
                String s=c+""+str.charAt(i);
                map.put(s,map.getOrDefault(s,0l)+dp[ch]);
                ans=Math.max(ans,map.get(s));
            }
            dp[ch]++;
            //debug(map);

            ans=Math.max(ans,dp[ch]);
        }
     //   debug(map);
        out.println(ans);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
    static void nl() throws Exception{
        pptr=0;
        st=br.readLine().split(" ");
    }
    static void nls() throws Exception{
        pptr=0;
        st=br.readLine().split("");
    }
    static int pi(){
        return Integer.parseInt(st[pptr++]);
    }
    static long pl(){
        return Long.parseLong(st[pptr++]);
    }
    static double pd(){
        return Double.parseDouble(st[pptr++]);
    }
    static String ps(){
        return st[pptr++];
    }
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000000000");
        out.print(ft.format(d));
    }
/**************************************Bit Manipulation**************************************************/
    static void printMask(long mask){
        System.out.println(Long.toBinaryString(mask));
    }
    static int countBit(long mask){
        int ans=0;
        while(mask!=0){
            mask&=(mask-1);
            ans++;
        }
        return ans;
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new ArrayList[n];
        for(int i=0;i<n;i++){
            graph[i]=new ArrayList<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(b);
    }
    // static void addEdge(int a,int b,int c){
    //     graph[a].add(new Pair(b,c));
    // }
/*********************************************PAIR********************************************************/
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }
        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }
        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }
        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }
/******************************************Long Pair*******************************************************/
    static class Pairl implements Comparable<Pairl> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }
            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }
            public boolean equals(Object o) {
                Pairl other = (Pairl) o;
                return u == other.u && v == other.v;
            }
            public int compareTo(Pairl other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }
            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o){
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c){
        long x=1;
        long y=a%c;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y){
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0){
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}