Problem:
Score : 200 points

Problem Statement

You are given a string S of length N consisting of lowercase English letters.
We will cut this string at one position into two strings X and Y.
Here, we would like to maximize the number of different letters contained in both X and Y.
Find the largest possible number of different letters contained in both X and Y when we cut the string at the optimal position.

Constraints

2 \leq N \leq 100

|S| = N

S consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the largest possible number of different letters contained in both X and Y.

Sample Input 1

6
aabbca

Sample Output 1

2

If we cut the string between the third and fourth letters into X = aab and Y = bca, the letters contained in both X and Y are a and b.
There will never be three or more different letters contained in both X and Y, so the answer is 2.

Sample Input 2

10
aaaaaaaaaa

Sample Output 2

1

However we divide S, only a will be contained in both X and Y.

Sample Input 3

45
tgxgdqkyjzhyputjjtllptdfxocrylqfqjynmfbfucbir

Sample Output 3

9

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)


import java.util.Comparator;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Arrays;
	/* static int java.util.Arrays.binarySearch(int[] a, int key); */
import java.math.BigDecimal;
	



public class Main {
	Scanner sc = new Scanner(System.in);
	int n;
	String s;
	public void run(){
		n = sc.nextInt();
		s = sc.next();
		solve();
	}
	
	public void solve(){
		int max = 0;
		String[] words = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
				"k", "l","m","n", "o", "p", "q", "r", "s", "t", "u", "v",
				"w", "x", "y", "z"
		};
		for(int i = 0; i < n; i++){
			String s1 = s.substring(0, i);
			String s2 = s.substring(i, n);
			
			int nmax = 0;
			for(int j = 0; j < 26; j++){
				if(s1.contains(words[j]) && s2.contains(words[j])){
					nmax++;
				}
			}
			
			if(max < nmax){
				max = nmax;
			}
			
		}
		System.out.println(max);
	}
	
	public static void main(String[] args){
		new Main().run();
	}
	
	static class Pair {
        int first,second;
        public Pair(int a,int b) {
            this.first = a;
            this.second = b;
        }
    }
	static class Edge{
		int to, cost;
		public Edge(int a, int b){
			this.to = a;
			this.cost = b;
		}
	}
	class MyComparator implements Comparator {
		@Override
		public int compare (Object arg0, Object arg1) {
			int x = ((Pair)arg0).first;
			int y = ((Pair)arg1).first;
			
			if (x < y) {
				return 1;
			} else if (x > y) {
				return -1;
			} else{
				return 0;
			}
		}
	}
	static class UnionFind{
		int par[];
		int rank[];
		
		//n要素で初期化
		public UnionFind(int maxn){
			par = new int[maxn];
			rank = new int[maxn];
			
			for(int i = 0; i < maxn; i++){
				par[i] = i;
				rank[i] = 0;
			}
		}
		
		//木の根を求める
		int find(int x){
			if(par[x] == x){
				return x;
			}
			else {
				return par[x] = find(par[x]);
			}
		}
		
		// xとyの属する集合を併合
		void unite (int x, int y){
			x = find(x);
			y = find(y);
			if(x == y){
				return;
			}
			
			if(rank[x] < rank[y]){
				par[x] = y;
			}
			else{
				par[y] = x;
				if(rank[x] == rank[y]) rank[x]++;
			}
		}
		
		// xとyが同じ集合に属するか否か
		boolean same(int x, int y){
			return find(x) == find(y);
		}
	}
	
}