codeparrot/codecomplex huggingface dataset:
// Problem: 1238_E. Keyboard Purchase
// Time complexity: np

/**
 * @author egaeus
 * @mail sebegaeusprogram@gmail.com
 * @veredict Accepted
 * @url <https://codeforces.com/problemset/problem/1238/E>
 * @category dp
 * @date 19/10/2019
 **/

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

import static java.lang.Integer.bitCount;
import static java.lang.Integer.parseInt;

public class CF1238E {
    static long[][] Q;
    static int N;
    static int M;
    static long[] mem;
    static long[] sums;

    public static void main(String args[]) throws Throwable {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for (String ln; (ln = in.readLine()) != null; ) {
            StringTokenizer st = new StringTokenizer(ln);
            N = parseInt(st.nextToken());
            M = parseInt(st.nextToken());
            char[] S = in.readLine().toCharArray();
            Q = new long[M][M];
            mem = new long[1 << M];
            Arrays.fill(mem, -1);
            for (int i = 1; i < N; i++)
                Q[S[i - 1] - 'a'][S[i] - 'a'] = Q[S[i] - 'a'][S[i - 1] - 'a'] = Q[S[i - 1] - 'a'][S[i] - 'a'] + 1;
            calculateSums();
            for (int i = (1 << M) - 1; i >= 0; i--)
                f(i);
            System.out.println(f(0));
        }
    }

    static void calculateSums() {
        sums = new long[1 << M];
        Arrays.fill(sums, -1);
        for (int u = 0; u < (1 << M); u++) {
            if (sums[u] == -1) {
                sums[u] = 0;
                for (int j = 0; j < M; j++)
                    for (int k = j + 1; k < M; k++)
                        if (((u & (1 << j)) == 0 && (u & (1 << k)) != 0) ||
                                ((u & (1 << j)) != 0 && (u & (1 << k)) == 0))
                            sums[u] += Q[j][k];
                int neg = (~u) & ((1 << M) - 1);
                sums[neg] = sums[u];
            }
        }
    }

    static long f(int u) {
        if (bitCount(u) == M) return 0;
        if (mem[u] >= 0)
            return mem[u];
        long min = 10000000000L;
        for (int i = 0; i < M; i++)
            if ((u & (1 << i)) == 0) {
                u = u | (1 << i);
                min = Math.min(f(u) + sums[u], min);
                u = u ^ (1 << i);
            }
        return mem[u] = min;
    }
}
// Problem: 1238_E. Keyboard Purchase
// Time complexity: np
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        char[] arr = br.readLine().toCharArray();
        int[][] count = new int[m][m];
        for (int i = 0; i < n - 1; i++) {
            count[arr[i] - 'a'][arr[i + 1] - 'a']++;
            count[arr[i + 1] - 'a'][arr[i] - 'a']++;
        }
        int[] memo = new int[1 << m];
        Arrays.fill(memo, (int) 1e9);
        memo[0] = 0;
        for (int msk = 0; msk < 1 << m; msk++) {
            for (int c = 0; c < m; c++) {
                if ((msk & 1 << c) != 0)
                    continue;
                int temp = 0;
                for (int i = 0; i < m; i++) {
                    if (i == c)
                        continue;
                    if ((msk & 1 << i) != 0) {
                        temp += count[c][i];
                    } else
                        temp -= count[c][i];
                }
                memo[msk | 1 << c] = Math.min(memo[msk | 1 << c], temp*Integer.bitCount(msk) + memo[msk]);
            }
        }
        System.out.println(memo[(1 << m) - 1]);
    }
}
// Problem: 1238_E. Keyboard Purchase
// Time complexity: np
import java.util.*;
import java.io.*;

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

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		out.println(work());
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return b==0?a:gcd(b,a%b);
	}
	long work() {
		int n=in.nextInt();
		int m=in.nextInt();
		String str=in.next();
		long[] dp=new long[1<<m];
		long[][] cnt=new long[m][m];
		long[] rec=new long[1<<m];//记录每次移动的一位怎加的值，减少重复计算
		for(int i=1;i<n;i++) {
			int n1=str.charAt(i-1)-'a';
			int n2=str.charAt(i)-'a';
			cnt[n1][n2]++;
			cnt[n2][n1]++;
		}
		for(int i=1;i<1<<m;i++) {
			dp[i]=9999999999L;
			long v=0;
			int b=0;//最低位的1
			for(int j=0;j<m;j++) {
				if((i&(1<<j))>0) {
					b=j;
					break;
				}
			}
			for(int j=0;j<m;j++) {
				if((i&(1<<j))==0) {
					v+=cnt[b][j];
				}else {
					if(b!=j)v-=cnt[b][j];
				}
			}
			v+=rec[i-(1<<b)];
			for(int j=0;j<m;j++) {
				if((i&(1<<j))>0) {
					dp[i]=Math.min(dp[i], dp[i-(1<<j)]+v);
				}
			}
			rec[i]=v;
		}
		
		return dp[(1<<m)-1];
	}
}



class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

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

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

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}
// Problem: 1238_E. Keyboard Purchase
// Time complexity: np

/**
 * @author Juan Sebastian Beltran Rojas
 * @mail jsbeltran.valhalla@gmail.com
 * @veredict
 * @url https://codeforces.com/problemset/problem/1238/E
 * @category dp
 * @date 19/10/2019
 **/

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

import static java.lang.Integer.bitCount;
import static java.lang.Integer.parseInt;

public class CF1238E {
    static long[][] Q;
    static int N;
    static int M;
    static long[] mem;
    static long[] sums;

    public static void main(String args[]) throws Throwable {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for (String ln; (ln = in.readLine()) != null; ) {
            StringTokenizer st = new StringTokenizer(ln);
            N = parseInt(st.nextToken());
            M = parseInt(st.nextToken());
            char[] S = in.readLine().toCharArray();
            Q = new long[M][M];
            mem = new long[1 << M];
            Arrays.fill(mem, -1);
            for (int i = 1; i < N; i++)
                Q[S[i - 1] - 'a'][S[i] - 'a'] = Q[S[i] - 'a'][S[i - 1] - 'a'] = Q[S[i - 1] - 'a'][S[i] - 'a'] + 1;
            calculateSums();
            for (int i = (1 << M) - 1; i >= 0; i--)
                f(i);
            System.out.println(f(0));
        }
    }

    static void calculateSums() {
        sums = new long[1 << M];
        Arrays.fill(sums, -1);
        for (int u = 0; u < (1 << M); u++) {
            if (sums[u] == -1) {
                sums[u] = 0;
                for (int j = 0; j < M; j++)
                    for (int k = j + 1; k < M; k++)
                        if (((u & (1 << j)) == 0 && (u & (1 << k)) != 0) ||
                                ((u & (1 << j)) != 0 && (u & (1 << k)) == 0))
                            sums[u] += Q[j][k];
                int neg = (~u) & ((1 << M) - 1);
                sums[neg] = sums[u];
            }
        }
    }

    static long f(int u) {
        if (bitCount(u) == M) return 0;
        if (mem[u] >= 0)
            return mem[u];
        long min = 10000000000L;
        for (int i = 0; i < M; i++)
            if ((u & (1 << i)) == 0) {
                u = u | (1 << i);
                min = Math.min(f(u) + sums[u], min);
                u = u ^ (1 << i);
            }
        return mem[u] = min;
    }
}