import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.Collections;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE2 solver = new TaskE2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskE2 {
        int[][] grid;
        int[][] val;
        int[][] dp;
        int rows;

        int two(int bit) {
            return 1 << bit;
        }

        boolean contain(int mask, int bit) {
            return (mask & two(bit)) > 0;
        }

        int rec(int col, int mask) {
            if (col == grid[0].length)
                return 0;

            if (dp[col][mask] != -1)
                return dp[col][mask];

            int res = rec(col + 1, mask);
            for (int newMask = mask; newMask > 0; newMask = (mask & (newMask - 1))) {
                res = Math.max(res, rec(col + 1, mask ^ newMask) + val[col][newMask]);
            }

            dp[col][mask] = res;
            return res;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int T = in.nextInt();
            for (int t = 0; t < T; t++) {

                int n = in.nextInt();
                int m = in.nextInt();
                rows = n;

                int[][] input = new int[n][m];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        input[i][j] = in.nextInt();
                    }
                }

                ArrayList<Col> cols = new ArrayList<>();
                for (int col = 0; col < m; col++) {
                    int maxVal = 0;
                    for (int row = 0; row < n; row++) {
                        maxVal = Math.max(maxVal, input[row][col]);
                    }
                    cols.add(new Col(maxVal, col));
                }
                Collections.sort(cols);

                m = Math.min(n, m);

                grid = new int[n][m];
                for (int i = 0; i < m; i++) {
                    int c = cols.get(i).colID;
                    for (int row = 0; row < n; row++) {
                        grid[row][i] = input[row][c];
                    }
                }

                val = new int[m][two(n)];
                for (int c = 0; c < m; c++) {
                    for (int mask = 0; mask < two(n); mask++) {
                        val[c][mask] = 0;
                        for (int offset = 0; offset < n; offset++) {
                            int sum = 0;
                            for (int bit = 0; bit < n; bit++) {
                                if (contain(mask, bit) == true)
                                    sum += grid[(bit + offset) % n][c];
                            }
                            val[c][mask] = Math.max(val[c][mask], sum);
                        }
                    }
                }

                dp = new int[m][two(n)];
                for (int[] aux : dp)
                    Arrays.fill(aux, -1);
                int ans = rec(0, two(n) - 1);
                out.println(ans);
            }
        }

        class Col implements Comparable<Col> {
            int maxVal;
            int colID;

            Col(int _maxVal, int _colID) {
                this.maxVal = _maxVal;
                this.colID = _colID;
            }

            public int compareTo(Col o) {
                if (o.maxVal != this.maxVal) return this.maxVal > o.maxVal ? -1 : 1;
                if (o.colID != this.colID) return this.colID < o.colID ? -1 : 1;
                return 0;
            }

        }

    }

    static class InputReader {
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputStream stream;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isWhitespace(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isWhitespace(c));
            return res * sgn;
        }

    }
}


import java.io.*;
import java.util.*;
public class Sol2{
	final public static int MXN = (1<<21);
	public static int good[][];
	public static void main(String[] args) throws IOException{
		FastIO sc = new FastIO(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int num[][] = new int[m][m];
		String str = sc.next();
		for(int i=0; i<str.length()-1; i++) {
			int a = str.charAt(i)-'a';
			int b = str.charAt(i+1)-'a';
			num[a][b]++;
			num[b][a]++;
		}
		int lowbit[] = new int[MXN];
		int dp[] = new int[MXN];
		for(int i=0; i<MXN; i++) {
			dp[i] = Integer.MAX_VALUE;
		}
		dp[0] = 0;
		good = new int[MXN][m];
		for(int msk = 0; msk<(1<<m); msk++) {
			for(int i=0; i<m; i++) {
				int low = Integer.numberOfTrailingZeros(Integer.lowestOneBit(msk));
				if(low==32) low = 0;
				good[msk][i] = good[msk^(1<<low)][i] + num[i][low];
			}
		}
		for(int msk = 0; msk<(1<<m); msk++) {
			int bits = Integer.bitCount(msk)+1;
			for(int i=0; i<m; i++) {
				if((msk&(1<<i))!=0) continue;
				int nxt = msk|(1<<i);
				dp[nxt] = Math.min(dp[nxt], dp[msk] + bits*(good[msk][i]-good[((1<<m)-1)^nxt][i]));
			}
		}
		out.println(dp[(1<<m)-1]);
		out.close();
	}
	static void shuffle(int[] a) {
		Random get = new Random();
		for (int i = 0; i < a.length; i++) {
			int r = get.nextInt(a.length);
			int temp = a[i];
			a[i] = a[r];
			a[r] = temp;
		}
	}
	static class FastIO {

		// Is your Fast I/O being bad?

		InputStream dis;
		byte[] buffer = new byte[1 << 17];
		int pointer = 0;

		public FastIO(String fileName) throws IOException {
			dis = new FileInputStream(fileName);
		}

		public FastIO(InputStream is) throws IOException {
			dis = is;
		}

		int nextInt() throws IOException {
			int ret = 0;

			byte b;
			do {
				b = nextByte();
			} while (b <= ' ');
			boolean negative = false;
			if (b == '-') {
				negative = true;
				b = nextByte();
			}
			while (b >= '0' && b <= '9') {
				ret = 10 * ret + b - '0';
				b = nextByte();
			}

			return (negative) ? -ret : ret;
		}

		long nextLong() throws IOException {
			long ret = 0;

			byte b;
			do {
				b = nextByte();
			} while (b <= ' ');
			boolean negative = false;
			if (b == '-') {
				negative = true;
				b = nextByte();
			}
			while (b >= '0' && b <= '9') {
				ret = 10 * ret + b - '0';
				b = nextByte();
			}

			return (negative) ? -ret : ret;
		}

		byte nextByte() throws IOException {
			if (pointer == buffer.length) {
				dis.read(buffer, 0, buffer.length);
				pointer = 0;
			}
			return buffer[pointer++];
		}

		String next() throws IOException {
			StringBuffer ret = new StringBuffer();

			byte b;
			do {
				b = nextByte();
			} while (b <= ' ');
			while (b > ' ') {
				ret.appendCodePoint(b);
				b = nextByte();
			}

			return ret.toString();
		}

	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.FilterInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Jenish
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        ScanReader in = new ScanReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        EKeyboardPurchase solver = new EKeyboardPurchase();
        solver.solve(1, in, out);
        out.close();
    }

    static class EKeyboardPurchase {
        public void solve(int testNumber, ScanReader in, PrintWriter out) {
            int n = in.scanInt();
            int m = in.scanInt();
            int step[][] = new int[m][m];
            char arr[] = in.scanString().toCharArray();
            for (int i = 0; i < n - 1; i++) {
                step[arr[i] - 'a'][arr[i + 1] - 'a']++;
                step[arr[i + 1] - 'a'][arr[i] - 'a']++;
            }

            int dp[] = new int[1 << m];
            Arrays.fill(dp, Integer.MAX_VALUE / 2);
            for (int i = 0; i < m; i++) dp[1 << i] = 0;
            for (int i = 0; i < (1 << m); i++) {
                int cost = 0;
                for (int j = 0; j < m; j++) {
                    if (((i & (1 << j)) != 0)) {
                        for (int k = 0; k < m; k++) {
                            if (((i & (1 << k)) == 0)) {
                                cost += step[j][k];
                            }
                        }
                    }
                }

                for (int j = 0; j < m; j++)
                    if (((i & (1 << j)) == 0)) dp[i | (1 << j)] = Math.min(dp[i | (1 << j)], dp[i] + cost);

            }

            out.println(dp[(1 << m) - 1]);

        }

    }

    static class ScanReader {
        private byte[] buf = new byte[4 * 1024];
        private int INDEX;
        private BufferedInputStream in;
        private int TOTAL;

        public ScanReader(InputStream inputStream) {
            in = new BufferedInputStream(inputStream);
        }

        private int scan() {
            if (INDEX >= TOTAL) {
                INDEX = 0;
                try {
                    TOTAL = in.read(buf);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (TOTAL <= 0) return -1;
            }
            return buf[INDEX++];
        }

        public int scanInt() {
            int I = 0;
            int n = scan();
            while (isWhiteSpace(n)) n = scan();
            int neg = 1;
            if (n == '-') {
                neg = -1;
                n = scan();
            }
            while (!isWhiteSpace(n)) {
                if (n >= '0' && n <= '9') {
                    I *= 10;
                    I += n - '0';
                    n = scan();
                }
            }
            return neg * I;
        }

        public String scanString() {
            int c = scan();
            while (isWhiteSpace(c)) c = scan();
            StringBuilder RESULT = new StringBuilder();
            do {
                RESULT.appendCodePoint(c);
                c = scan();
            } while (!isWhiteSpace(c));
            return RESULT.toString();
        }

        private boolean isWhiteSpace(int n) {
            if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
            else return false;
        }

    }
}


/*
If you want to aim high, aim high
Don't let that studying and grades consume you
Just live life young
******************************
If I'm the sun, you're the moon
Because when I go up, you go down
*******************************
I'm working for the day I will surpass you
https://www.a2oj.com/Ladder16.html
*/
import java.util.*;
import java.io.*;
import java.math.*;

   public class x1238E
   {
      public static void main(String omkar[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = new StringTokenizer(infile.readLine());
         int N = Integer.parseInt(st.nextToken());
         int M = Integer.parseInt(st.nextToken());
         String input = infile.readLine();
         int[][] cnt = new int[M][M];
         for(int i=0; i < N-1; i++)
         if(input.charAt(i) != input.charAt(i+1))
            {
               cnt[input.charAt(i)-'a'][input.charAt(i+1)-'a']++;
               cnt[input.charAt(i+1)-'a'][input.charAt(i)-'a']++;
            }
         int[] dp = new int[1 << M];
         Arrays.fill(dp, Integer.MAX_VALUE);
         dp[0] = 0;
         for(int mask=0; mask < dp.length; mask++)
            for(int b=0; b < M; b++)
               if((mask&(1<<b)) == 0)
               {
                  int submask = mask|(1<<b);
                  int cost = 0;
                  for(int c=0; c < M; c++)
                  {
                     if((mask&(1<<c)) > 0)
                        cost += cnt[b][c];
                     else
                        cost -= cnt[b][c];
                  }
                  dp[submask] = Math.min(dp[submask], dp[mask]+cost*Integer.bitCount(mask));
               }
         System.out.println(dp[(1<<M)-1]);
      }
   }


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class Main
{
    static MyScanner scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null, null, "BaZ", 1 << 27) {
            public void run() {
                try {
                    solve();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int n,m;
    static int dp[], cnt[][], sum[];
    static void solve() throws IOException
    {
        //initIo(true);
        initIo(false);
        StringBuilder sb = new StringBuilder();
        n = ni();
        m = ni();
        dp = new int[(1<<m)];
        char c[] = ne().toCharArray();
        cnt = new int[m][m];
        for(int i=0;i+1<n;++i) {
            if(c[i]!=c[i+1]) {
                ++cnt[c[i] - 'a'][c[i+1] - 'a'];
                ++cnt[c[i+1] - 'a'][c[i] - 'a'];
            }
        }
        sum = new int[1<<m];
        calc(0, 0, 0);
        Arrays.fill(dp, -1);
        pl(f(0));
        pw.flush();
        pw.close();
    }
    static void calc(int mask, int S, int pos) {
        if(pos==m) {
            sum[mask] = S;
            return;
        }
        calc(mask, S, pos+1);
        int newSum = S;
        for(int i=0;i<pos;++i) {
            if((mask&(1<<i))!=0) {
                newSum-=cnt[i][pos];
            }
            else {
                newSum+=cnt[i][pos];
            }
        }
        for(int i=pos+1;i<m;++i) {
            newSum+=cnt[i][pos];
        }
        calc(mask|(1<<pos), newSum, pos+1);
    }
    static int f(int mask) {
        if(mask==(1<<m) - 1) {
            return 0;
        }
        if(dp[mask]!=-1) {
            return dp[mask];
        }
        int min = Integer.MAX_VALUE;
        for(int i=0;i<m;++i) {
            if((mask&(1<<i))==0) {
                min  =  min(min, sum[mask]+f(mask|(1<<i)));
            }
        }
        return dp[mask] = min;
    }
    static void initIo(boolean isFileIO) throws IOException {
        scan = new MyScanner(isFileIO);
        if(isFileIO) {
            pw = new PrintWriter("/Users/amandeep/Desktop/output.txt");
        }
        else {
            pw = new PrintWriter(System.out, true);
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static String ne() throws IOException
    {
        return scan.next();
    }
    static String nel() throws IOException
    {
        return scan.nextLine();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class MyScanner
    {
        BufferedReader br;
        StringTokenizer st;
        MyScanner(boolean readingFromFile) throws IOException
        {
            if(readingFromFile) {
                br = new BufferedReader(new FileReader("/Users/amandeep/Desktop/input.txt"));
            }
            else {
                br = new BufferedReader(new InputStreamReader(System.in));
            }
        }
        String nextLine()throws IOException
        {
            return br.readLine();
        }
        String next() throws IOException
        {
            if(st==null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }
        int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
    }
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class CF1238E {
    public static void main(String[] args) throws Exception {
        boolean local = System.getSecurityManager() == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        long lInf = (long) 1e18;
        double dInf = 1e50;

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        int[][] fee;
        int m;
        long[] dp;
        int mask;
        int[][] maskFee;

        public void solve() {
            int n = io.readInt();
            m = io.readInt();
            char[] s = new char[n];
            io.readString(s, 0);
            for (int i = 0; i < n; i++) {
                s[i] -= 'a';
            }
            fee = new int[m][m];
            for (int i = 1; i < n; i++) {
                fee[s[i]][s[i - 1]]++;
                fee[s[i - 1]][s[i]]++;
            }

            mask = (1 << m) - 1;
            maskFee = new int[m][mask + 1];
            SubsetGenerator sg = new SubsetGenerator();
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < m; j++) {
                    sg.meanings[j] = fee[i][j];
                }
                for (int j = 0; j <= mask; j++) {
                    maskFee[i][j] = sg.next();
                }
            }

            dp = new long[mask + 1];
            Arrays.fill(dp, -1);
            dp[0] = 0;

            io.cache.append(dp(mask));
        }

        BitOperator bo = new BitOperator();

        public long dp(int s) {
            if (dp[s] == -1) {
                long extra = 0;
                int remainSet = mask - s;
                for (int j = 0; j < m; j++) {
                    if (bo.bitAt(s, j) == 0) {
                        continue;
                    }
                    extra += maskFee[j][remainSet];
                }

                dp[s] = lInf;
                for (int j = 0; j < m; j++) {
                    if (bo.bitAt(s, j) == 0) {
                        continue;
                    }
                    int ss = bo.setBit(s, j, false);
                    dp[s] = Math.min(dp[s], extra + dp(ss));
                }
            }

            return dp[s];
        }
    }

    /**
     * Bit operations
     */
    public static class BitOperator {
        public int bitAt(int x, int i) {
            return (x >> i) & 1;
        }

        public int bitAt(long x, int i) {
            return (int) ((x >> i) & 1);
        }

        public int setBit(int x, int i, boolean v) {
            if (v) {
                x |= 1 << i;
            } else {
                x &= ~(1 << i);
            }
            return x;
        }

        public long setBit(long x, int i, boolean v) {
            if (v) {
                x |= 1L << i;
            } else {
                x &= ~(1L << i);
            }
            return x;
        }

        public long swapBit(long x, int i, int j) {
            int bi = bitAt(x, i);
            int bj = bitAt(x, j);
            x = setBit(x, i, bj == 1);
            x = setBit(x, j, bi == 1);
            return x;
        }

        public int swapBit(int x, int i, int j) {
            int bi = bitAt(x, i);
            int bj = bitAt(x, j);
            x = setBit(x, i, bj == 1);
            x = setBit(x, j, bi == 1);
            return x;
        }

        /**
         * Determine whether x is subset of y
         */
        public boolean subset(long x, long y) {
            return intersect(x, y) == x;
        }

        /**
         * Merge two set
         */
        public long merge(long x, long y) {
            return x | y;
        }

        public long intersect(long x, long y) {
            return x & y;
        }

        public long differ(long x, long y) {
            return x - intersect(x, y);
        }
    }

    public static class SubsetGenerator {
        private int[] meanings = new int[33];
        private int[] bits = new int[33];
        private int remain;
        private int next;

        public void setSet(int set) {
            int bitCount = 0;
            while (set != 0) {
                meanings[bitCount] = set & -set;
                bits[bitCount] = 0;
                set -= meanings[bitCount];
                bitCount++;
            }
            remain = 1 << bitCount;
            next = 0;
        }

        public boolean hasNext() {
            return remain > 0;
        }

        private void consume() {
            remain = remain - 1;
            int i;
            for (i = 0; bits[i] == 1; i++) {
                bits[i] = 0;
                next -= meanings[i];
            }
            bits[i] = 1;
            next += meanings[i];
        }

        public int next() {
            int returned = next;
            consume();
            return returned;
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder(1 << 13);
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 13);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() throws IOException {
            os.write(cache.toString().getBytes(charset));
            os.flush();
            cache.setLength(0);
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		//where's my 420??? :(

		n = fs.nextInt(); m = fs.nextInt();
		byte[] str = fs.next().getBytes();
		int[] occs = new int[1<<m];
		for(int i = 0; i < n-1; i++) {
			int l1 = str[i] - 'a';
			int l2 = str[i+1] - 'a';
			occs[(1<<l1) | (1<<l2)]++;
			occs[(1<<l2) | (1<<l1)]++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[1<<i | 1<<trail];
			}
		}

		dp = new int[1<<m];
		for(int mask = dp.length-2; mask >= 0; mask--) {
			int addOn = 0;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				addOn += cost[nxt][mask];
			}
			int res = oo;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				int ret = addOn+dp[mask | (1<<nxt)];
				res = min(res, ret);
			}
			dp[mask] = res;
		}

		System.out.println(dp[0]>>1);

		out.close();
	}

	int oo = (int)1e9;
	int min(int a, int b) {
		if(a < b) return a;
		return b;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.InputMismatchException;
import java.util.function.Function;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	static class TaskAdapter implements Runnable {
		@Override
		public void run() {
			long startTime = System.currentTimeMillis();
			InputStream inputStream = System.in;
			OutputStream outputStream = System.out;
			FastReader in = new FastReader(inputStream);
			Output out = new Output(outputStream);
			EKeyboardPurchase solver = new EKeyboardPurchase();
			solver.solve(1, in, out);
			out.close();
			System.err.println(System.currentTimeMillis()-startTime+"ms");
		}
	}

	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(null, new TaskAdapter(), "", 1<<28);
		thread.start();
		thread.join();
	}

	static class EKeyboardPurchase {
		private final int iinf = 1_000_000_000;

		public EKeyboardPurchase() {
		}

		public void solve(int kase, InputReader in, Output pw) {
			int n = in.nextInt(), m = in.nextInt();
			int[] arr = in.nextIntChar(o -> o-'a');
			int[][] sum = new int[m][1<<m];
			{
				int[][] cnt = new int[m][m];
				for(int i = 0; i<n-1; i++) {
					int a = arr[i], b = arr[i+1];
					cnt[a][b]++;
					cnt[b][a]++;
				}
				for(int i = 0; i<m; i++) {
					for(int j = 1; j<1<<m; j++) {
						int x = j&-j;
						sum[i][j] = sum[i][j^x]+cnt[i][31-Integer.numberOfLeadingZeros(x)];
					}
				}
			}
			int[] mbit = new int[1<<m];
			for(int i = 1; i<1<<m; i++) {
				mbit[i] = Integer.numberOfTrailingZeros(i&-i);
			}
			int[] dp = new int[1<<m];
			for(int i = 1; i<1<<m; i++) {
				int ans = iinf, ci = i;
				for(int j = mbit[ci]; ci>0; ci -= (1<<j), j = mbit[ci]) {
					int cur = dp[i^(1<<j)]+sum[j][i^(1<<j)];
					int x = ((1<<m)-1)^i;
					int cm = i;
					for(int k = mbit[cm]; cm>0; cm -= (1<<k), k = mbit[cm]) {
						cur += sum[k][x];
					}
					cur -= sum[j][x];
					ans = Math.min(ans, cur);
				}
				dp[i] = ans;
			}
//		dbg(dp);
			pw.println(dp[dp.length-1]);
		}

	}

	static interface InputReader {
		String next();

		int nextInt();

		default int[] nextIntChar(Function<Character, Integer> f) {
			String s = next();
			int[] ret = new int[s.length()];
			for(int i = 0; i<s.length(); i++) {
				ret[i] = f.apply(s.charAt(i));
			}
			return ret;
		}

	}

	static class FastReader implements InputReader {
		final private int BUFFER_SIZE = 1<<16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer;
		private int bytesRead;

		public FastReader(InputStream is) {
			din = new DataInputStream(is);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String next() {
			StringBuilder ret = new StringBuilder(64);
			byte c = skip();
			while(c!=-1&&!isSpaceChar(c)) {
				ret.appendCodePoint(c);
				c = read();
			}
			return ret.toString();
		}

		public int nextInt() {
			int ret = 0;
			byte c = skipToDigit();
			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;
		}

		private boolean isSpaceChar(byte b) {
			return b==' '||b=='\r'||b=='\n'||b=='\t'||b=='\f';
		}

		private byte skip() {
			byte ret;
			while(isSpaceChar((ret = read()))) ;
			return ret;
		}

		private boolean isDigit(byte b) {
			return b>='0'&&b<='9';
		}

		private byte skipToDigit() {
			byte ret;
			while(!isDigit(ret = read())&&ret!='-') ;
			return ret;
		}

		private void fillBuffer() {
			try {
				bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			}catch(IOException e) {
				e.printStackTrace();
				throw new InputMismatchException();
			}
			if(bytesRead==-1) {
				buffer[0] = -1;
			}
		}

		private byte read() {
			if(bytesRead==-1) {
				throw new InputMismatchException();
			}else if(bufferPointer==bytesRead) {
				fillBuffer();
			}
			return buffer[bufferPointer++];
		}

	}

	static class Output implements Closeable, Flushable {
		public StringBuilder sb;
		public OutputStream os;
		public int BUFFER_SIZE;
		public String lineSeparator;

		public Output(OutputStream os) {
			this(os, 1<<16);
		}

		public Output(OutputStream os, int bs) {
			BUFFER_SIZE = bs;
			sb = new StringBuilder(BUFFER_SIZE);
			this.os = new BufferedOutputStream(os, 1<<17);
			lineSeparator = System.lineSeparator();
		}

		public void println(int i) {
			println(String.valueOf(i));
		}

		public void println(String s) {
			sb.append(s);
			println();
		}

		public void println() {
			sb.append(lineSeparator);
		}

		private void flushToBuffer() {
			try {
				os.write(sb.toString().getBytes());
			}catch(IOException e) {
				e.printStackTrace();
			}
			sb = new StringBuilder(BUFFER_SIZE);
		}

		public void flush() {
			try {
				flushToBuffer();
				os.flush();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}

		public void close() {
			flush();
			try {
				os.close();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}

	}
}


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


import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

import static java.lang.Math.cos;
import static java.lang.Math.min;

public class E_fast {
    static int g[][];
    static int n, m;
    static char[] s;
    static int dp[], inf = (int) 2e9;
    static int cost[][];

    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = in.nextInt();
        m = in.nextInt();
        s = in.next().toCharArray();
        g = new int[m][m];
        for (int i = 1; i < n; i++) {
            int x = s[i - 1] - 'a', y = s[i] - 'a';
            if (x != y) {
                g[x][y]++;
                g[y][x]++;
            }
        }
        cost = new int[m][1 << m];
        for (int i = 0; i < m; i++) {
            int w = 0;
            for (int j = 0; j < m; j++) w += g[i][j];
            pre(i, 0, 0, -w);
        }
        dp = new int[1 << m];
        Arrays.fill(dp, -1);
        pw.println(solve(0, 0));

        pw.close();
    }

    static void pre(int x, int pos, int mask, int w) {
        if (pos >= m) {
            cost[x][mask] = w;
            return;
        }
        pre(x, pos + 1, mask, w);
        pre(x, pos + 1, set(mask, pos), w + 2 * g[x][pos]);
    }

    static int solve(int pos, int mask) {
        if (pos >= m) return 0;
        if (dp[mask] != -1) return dp[mask];
        int min = inf;
        for (int i = 0; i < m; i++) {
            if (!check(mask, i)) {
                int res = cost[i][mask] * pos + solve(pos + 1, set(mask, i));
                min = min(min, res);
            }
        }
        return dp[mask] = min;
    }

    static boolean check(int N, int pos) {
        return (N & (1 << pos)) != 0;
    }

    static int set(int N, int pos) {
        return N = N | (1 << pos);
    }

    static int reset(int N, int pos) {
        return N = N & ~(1 << pos);
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		//where's my 420???? :(
		long tot = 0;
		for(int i = 0; i < 20000; i++) tot += i;
		System.err.println(tot);

		n = fs.nextInt(); m = fs.nextInt();
		byte[] str = fs.next().getBytes();
		int[] occs = new int[1<<m];
		for(int i = 0; i < n-1; i++) {
			int l1 = str[i] - 'a';
			int l2 = str[i+1] - 'a';
			occs[(1<<l1) | (1<<l2)]++;
			occs[(1<<l2) | (1<<l1)]++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[1<<i | 1<<trail];
			}
		}

		dp = new int[1<<m];
		for(int mask = dp.length-2; mask >= 0; mask--) {
			int addOn = 0;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				addOn += cost[nxt][mask];
			}
			int res = oo;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				int ret = addOn+dp[mask | (1<<nxt)];
				res = min(res, ret);
			}
			dp[mask] = res;
		}

		System.out.println(dp[0]>>1);

		out.close();
	}

	int oo = (int)1e9;
	int min(int a, int b) {
		if(a < b) return a;
		return b;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;

	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);

	 	int n = sc.nextInt();
	 	int m = sc.nextInt();
	 	int[][]cnt = new int[m][m];
	 	String s = sc.next();
	 	for(int j =0;j<n-1;j++){
	 		if (s.charAt(j) != s.charAt(j+1)){
	 		cnt[s.charAt(j)-'a'][s.charAt(j+1)-'a']++;
	 		cnt[s.charAt(j+1)-'a'][s.charAt(j)-'a']++;
	 		}
	 	}
	 	int[] st = new int[m+1];
	 	for(int j = 0;j<=m;j++){
	 		st[j] = (1<<j);
	 	}
	 	int[][] arr = new int[m][1<<m];
	 	for(int j = 0;j<m;j++){
	 		for(int k = 1;k<(1<<m);k++){
	 			int z = Integer.lowestOneBit(k);
	 			int count = 0;
	 			while(z!=0 && z%2==0){
	 				z/=2;
	 				count++;
	 			}
	 			arr[j][k] = arr[j][k^(Integer.lowestOneBit(k))] + cnt[j][count];
	 		}
	 	}
	 	int[] dp = new int[1<<m];
	 	Arrays.fill(dp,  Integer.MAX_VALUE);
	 	dp[0] = 0;
	 	for(int j = 1;j<st[m];j++){

	 		for(int k = 0;k<m;k++){
	 			int y = st[k];
	 			if ((y&j) != 0){
	 				int sum = 2*arr[k][j] - arr[k][(1<<m)-1];
//	 				for(int t = 0;t<m;t++){
//	 					if (t!= k){
//		 					if ((st[t]&j) != 0)
//		 						sum+=cnt[t][k];
//		 					else
//		 						sum-=cnt[t][k];
//	 					}
//	 				}
	 				dp[j] = Math.min(dp[j],  dp[y^j]+sum*Integer.bitCount(j));
	 			}
	 		}
	 	}
	 	out.println(dp[(1<<m)-1]);
 		out.close();
 	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
	static void verdict(boolean a){
        out.println(a ? "YES" : "NO");
    }
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            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;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		n = fs.nextInt(); m = fs.nextInt();
		str = fs.next().toCharArray();
		occs = new int[m][m];
		for(int i = 0; i < n-1; i++) {
			occs[str[i]-'a'][str[i+1]-'a']++;
			occs[str[i+1]-'a'][str[i]-'a']++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[i][trail];
			}
		}

		dp = new int[1<<m];
		Arrays.fill(dp, -1);
		System.out.println(solve(0));

		out.close();
	}

	int oo = (int)1e9;
	int solve(int mask) {
		if(mask == (1<<m)-1) return 0;
		if(dp[mask] != -1) return dp[mask];
		int res = oo;

		int addOn = 0;
		for(int nxt = 0; nxt < m; nxt++) {
			if(((1<<nxt)&mask) > 0) continue;
			addOn += cost[nxt][mask];
		}
		for(int nxt = 0; nxt < m; nxt++) {
			if(((1<<nxt)&mask) > 0) continue;
			int ret = addOn+solve(mask | (1<<nxt));
			res = Math.min(res, ret);
		}

		return dp[mask] = res;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		//where's my 420???? :(

		n = fs.nextInt(); m = fs.nextInt();
		byte[] str = fs.next().getBytes();
		int[] occs = new int[1<<m];
		for(int i = 0; i < n-1; i++) {
			int l1 = str[i] - 'a';
			int l2 = str[i+1] - 'a';
			occs[(1<<l1) | (1<<l2)]++;
			occs[(1<<l2) | (1<<l1)]++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[1<<i | 1<<trail];
			}
		}

		dp = new int[1<<m];
		for(int mask = dp.length-2; mask >= 0; mask--) {
			int addOn = 0;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				addOn += cost[nxt][mask];
			}
			int res = oo;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				int ret = addOn+dp[mask | (1<<nxt)];
				res = min(res, ret);
			}
			dp[mask] = res;
		}

		System.out.println(dp[0]>>1);

		out.close();
	}

	int oo = (int)1e9;
	int min(int a, int b) {
		if(a < b) return a;
		return b;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class Main {
	static int t,m,mod=998244353,maxn=1000000,q,n,k;
    static int INF=(int)1e8;

    void solve(PrintWriter out, Reader in) throws IOException{
        n = in.nextInt();
        m = in.nextInt();

        String str = in.next();
        int[][] pre = new int[1<<m][m];

        int child=0,head,child2=0;
        for(int i=0;i<n;i++){
            if(i!=0) child = 1<<(str.charAt(i-1)-'a');
            if(i!=n-1) child2 = 1<<(str.charAt(i+1)-'a');
            head = str.charAt(i)-'a';

            if(i!=0) pre[child][head]++;
            if(i!=n-1) pre[child2][head]++;
        }

        //pre[child][head] - number of elemnts that exists in child and are adjacent to head in the string.

        int rmv=0;
        for(int i=0;i<m;i++){
            head = i;
            for(int j=1;j<1<<m;j++){
                if(pre[j][i]!=0) continue;

                rmv = j-(j&-j);
                pre[j][head] = pre[rmv][head]+pre[j^rmv][head];
            }
        }

        int[] dp = new int[1<<m];
        for(int i=1;i<1<<m;i++) dp[i] = INF;

        // dp[mask] - the minimum cost using a permutation of the set bits in the mask.

        int bit=0,full=(1<<m)-1,cnt=0;
        for(int j=1;j<1<<m;j++){
            for(int i=0;i<m;i++){
                if(((1<<i)&j)!=0){
                    bit = 1<<i;
                    cnt = cnt(j);
                    dp[j] = Math.min(dp[j],dp[j^bit]+pre[j^bit][i]*cnt-pre[j^full][i]*cnt);
                }
            }
        }

        out.println(dp[full]);
    }

    static int cnt(int x){
        int res=0;
        while(x>0){
            res+=x&1;
            x>>=1;
        }
        return res;
    }

    static class Reader {

    private InputStream mIs;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;

    public Reader() {
        this(System.in);
    }

    public Reader(InputStream is) {
        mIs = is;
    }

    public int read() {
        if (numChars == -1) {
            throw new InputMismatchException();

    }
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = mIs.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0) {
                return -1;
            }
        }
        return buf[curChar++];
    }

    public String nextLine() {
        int c = read();
        while (isSpaceChar(c)) {
            c = read();
        }
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isEndOfLine(c));
        return res.toString();
    }

    public String next() {
        int c = read();
        while (isSpaceChar(c)) {
            c = read();
        }
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));
        return res.toString();
    }

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

    public long nextLong() {
        int c = read();
        while (isSpaceChar(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        long res = 0;
        do {
            if (c < '0' || c > '9') {
                throw new InputMismatchException();
            }
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public int nextInt() {
        int c = read();
        while (isSpaceChar(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9') {
                throw new InputMismatchException();
            }
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public boolean isEndOfLine(int c) {
        return c == '\n' || c == '\r' || c == -1;
    }

    }
    public static void main(String[] args) throws IOException {
        PrintWriter out = new PrintWriter(System.out);
        Reader in = new Reader();
        Main solver = new Main();
        solver.solve(out, in);
        out.flush();
        out.close();

    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		//where's my 420???? :(
		long tot = 0;
		for(int i = 0; i < 20000; i++) tot += i;

		n = fs.nextInt(); m = fs.nextInt();
		byte[] str = fs.next().getBytes();
		int[] occs = new int[1<<m];
		for(int i = 0; i < n-1; i++) {
			int l1 = str[i] - 'a';
			int l2 = str[i+1] - 'a';
			occs[(1<<l1) | (1<<l2)]++;
			occs[(1<<l2) | (1<<l1)]++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[1<<i | 1<<trail];
			}
		}

		dp = new int[1<<m];
		for(int mask = dp.length-2; mask >= 0; mask--) {
			int addOn = 0;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				addOn += cost[nxt][mask];
			}
			int res = oo;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				int ret = addOn+dp[mask | (1<<nxt)];
				res = min(res, ret);
			}
			dp[mask] = res;
		}

		System.out.println(dp[0]>>1);

		out.close();
	}

	int oo = (int)1e9;
	int min(int a, int b) {
		if(a < b) return a;
		return b;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class KeyboardPurchase {
    static final int INF = 1000000000;
    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out, false);
        int N = in.nextInt(), M = in.nextInt();
        String str = in.next();
        int[][] count = new int[M][M];
        for (int i = 1; i < N; i++) {
            char c1 = str.charAt(i - 1), c2 = str.charAt(i);
            count[c1 - 'a'][c2 - 'a']++;
            count[c2 - 'a'][c1 - 'a']++;
        }
        int[] dp = new int[(1 << M)];
        Arrays.fill(dp, INF);
        dp[0] = 0;
        for (int mask = 1; mask < (1 << M); mask++) {
            int slow = 0;
            for (int i = 0; i < M; i++) {
                if ((mask & (1 << i)) != 0) {
                    for (int j = 0; j < M; j++) {
                        if ((mask & (1 << j)) == 0) {
                            slow += count[i][j];
                        }
                    }
                }
            }
            for (int i = 0; i < M; i++) {
                if ((mask & (1 << i)) != 0) {
                    dp[mask] = Math.min(dp[mask], slow + dp[mask ^ (1 << i)]);
                }
            }
        }
        out.println(dp[(1 << M) - 1]);
        out.close();
        System.exit(0);
    }
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
        public String nextLine() {
            String str = "";
            try {
                str = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.util.Arrays;
import java.util.Scanner;

public class thing {

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

		int n = in.nextInt();
		int m = in.nextInt();

		String s = in.next();

		int[][] count = new int[m][m];
		int[] dp = new int[1 << m];

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

		for(int i = 1; i < n; i++) {
			int a = s.charAt(i)-'a';
			int b = s.charAt(i-1)-'a';
			count[a][b]++;
			count[b][a]++;
		}

		for(int i = 1; i < (1 << m); i++) {

			int pos = set_bits(i);

			for(int j = 0; (i >> j) != 0; j++) {

				if(((i >> j) & 1) == 0) continue;

				int sum = 0;

				for(int mask = i, y = 0; y < m; mask >>= 1, y++) {
					if(y == j) continue;
					if((mask & 1) == 1) sum += count[j][y];
					else sum -= count[j][y];
				}

				int calc = dp[i-(1<<j)] + pos*sum;

				dp[i] = Math.min(dp[i], calc);
			}

		}

		System.out.println(dp[(1 << m)-1]);

	}

	public static int set_bits(int n) {
		int count = 0;
		while (n > 0) {
			count += n & 1;
			n >>= 1;
		}
		return count;
	}

}


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

public class cfe {
	static DataReader input;
	static int LARGE_INT = 1000000007;
	//static int MAXN = 300000;
	//static int[] len = new int[300000];
	//static int[] price = new int[300000];
	static final int[] BM =  {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
	                          1<<17, 1<<18, 1<<19, 1<<20};

	public static void main(String[] args) throws IOException {
	    input = new DataReader();
		PrintWriter out = new PrintWriter(System.out);
		int N = nextInt(), M = nextInt(), P = 1<<M;
		String x = nextStr();
		int c1 = x.charAt(0) - 'a';
		int[][] pair_count = new int[M][M];
		for (int i=1; i<N; i++) {
			int c2 = x.charAt(i) - 'a';
			if (c1 < c2)
				pair_count[c1][c2]++;
			else if (c1 > c2)
				pair_count[c2][c1]++;
			c1 = c2;
		}
		int[] group_count = new int[P];
		for (int mask = 1; mask <P; mask++) {
			int j;
			for (j=0; j<M; j++) {
				if ((mask & BM[j]) > 0)  break;
			}
			int nmask = mask ^ BM[j];
			int val = group_count[nmask];
			for (int i=0; i<j; i++) {
				if ((mask & BM[i]) > 0)  val -= pair_count[i][j];
				else                   val += pair_count[i][j];
			}
			for (int i=j+1; i<M; i++) {
				if ((mask & BM[i]) > 0)  val -= pair_count[j][i];
				else                   val += pair_count[j][i];
			}
			group_count[mask] = val;
		}
		// dp[k][mask] = Accumulated cost of first K positions filled, mask position 1 letters are used
		// dp[0][0] = 0;
		int[][] dp = new int[M+1][P];	   //
		for (int mask=1; mask<P; mask++) {  // each bit mask
			dp[0][mask] = 0;
			int k = Integer.bitCount(mask);  // computing first k position filled.
			int val = LARGE_INT;
			for (int j=0; j<M; j++) {
				if ((mask & BM[j]) > 0) {
					int nmask = mask ^ BM[j];
					val = Math.min(val, dp[k-1][nmask] + group_count[nmask]);
				}
			}
			dp[k][mask] = val;
		}
		//out.println(Arrays.deepToString(dp));
		out.println(dp[M][P-1]);
		out.flush();
		out.close();
	}
	static int nextInt() throws IOException {
        return Integer.parseInt(input.next());
    }
	static String nextStr() throws IOException {
        return input.next();
    }
    static class DataReader {
        BufferedReader br;
        StringTokenizer st;
        public DataReader() throws IOException {	// reading from standard in
			br = new BufferedReader(new InputStreamReader(System.in));
        }
		boolean hasNext() throws IOException {
            while (st == null || !st.hasMoreElements()) {
				String line = br.readLine();
				if (line == null) { // end of file
					return false;
				}
                st = new StringTokenizer(line);
            }
			return true;
		}
        String next() throws IOException {
			if (hasNext())
				return st.nextToken();
			else
				return null;
        }
    }
}


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

public class E {
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        PrintWriter out = new PrintWriter(System.out, false);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        char[] str = scanner.next().toCharArray();
        int maxMask = 1 << m;
        long[] dp = new long[maxMask];
        int[][] dists = new int[m][m];
        for(int i = 1; i < n; i++) {
            int c1 = str[i] - 'a';
            int c2 = str[i-1] - 'a';
            dists[c1][c2]++;
            dists[c2][c1]++;
        }
        int[] pre = new int[maxMask];
        for(int mask = 0; mask < maxMask; mask++) {
            for(int i = 0; i < m; i++) {
                if (((1 << i) & mask) == 0) continue;
                for(int j = 0; j < m; j++) {
                    if (((1 << j) & mask) > 0) continue;
                    pre[mask] += dists[i][j];
                }
            }
        }
        Arrays.fill(dp, Long.MAX_VALUE/4);
        dp[0] = 0;
        for(int mask = 0; mask < maxMask; mask++) {
            if (dp[mask] == Long.MAX_VALUE/4) continue;
            for(int i = 0; i < m; i++) {
                if (((1 << i) & mask) > 0) continue;
                int nmask = mask | (1 << i);
                dp[nmask] = Math.min(dp[nmask], dp[mask] + pre[nmask]);
            }
        }
        out.println(dp[maxMask - 1]);
        out.flush();
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(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 readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


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

public class E
{
	public static void main(String[] args) throws IOException
	{new E();}

	FastScanner in = new FastScanner(System.in);
	PrintWriter out = new PrintWriter(System.out);

	int n, m, oo = 1 << 28;
	int[] dp, cost;
	int[][] to;
	char[] w;

	E() throws IOException
	{
		n = in.nextInt();
		m = in.nextInt();
		w = in.next().toCharArray();
		to = new int[m+1][m+1];
		for (int i = 0; i < n-1; i++)
			if (w[i] != w[i+1])
			{
				to[w[i]-'a'][w[i+1]-'a']++;
				to[w[i+1]-'a'][w[i]-'a']++;
			}

		cost = new int[1 << m];
		for (int i = 0; i < (1 << m); i++)
			for (int j = 0; j < m; j++)
			{
				if (((1 << j) & i) > 0)
					continue;
				for (int k = 0; k < m; k++)
				{
					if (((1 << k) & i) == 0)
						continue;
					cost[i] += to[j][k];
				}
			}

		dp = new int[1 << m];
		Arrays.fill(dp, oo);
		dp[0] = 0;
		for (int i = 1; i < (1 << m); i++)
		{
			for (int j = 0; j < m; j++)
				if (((i >> j) & 1) > 0)
					dp[i] = Math.min(dp[i], dp[i ^ (1 << j)]);
			dp[i] += cost[i];
		}
		out.println(dp[(1 << m)-1]);
		out.close();
	}

	void sort(int[] x)
	{
		int sz = x.length;
		Random r = new Random();
		for (int i = 0; i < sz; i++)
		{
			int j = r.nextInt(sz);
			x[i] = x[j]-(x[i]-(x[j] = x[i]));
		}
		Arrays.sort(x);
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;
		public FastScanner(InputStream i) {
		    br = new BufferedReader(new InputStreamReader(i));
		    st = new StringTokenizer("");
		}
		public String next() throws IOException {
		    if(st.hasMoreTokens())
		        return st.nextToken();
		    else
		        st = new StringTokenizer(br.readLine());
		    return next();
		}
		public int nextInt() throws IOException {
		    return Integer.parseInt(next());
		}
		public int[] intarr(int n) throws IOException {
			int[] res = new int[n];
			for (int i = 0; i < n; i++)
				res[i] = nextInt();
			return res;
		}
	    public long nextLong() throws IOException {
		    return Long.parseLong(next());
		}
		public double nextDouble() throws IOException {
		    return Double.parseDouble(next());
		}
    }
}


// practice with rainboy
import java.io.*;
import java.util.*;

public class CF1238E extends PrintWriter {
	CF1238E() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1238E o = new CF1238E(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		byte[] cc = sc.next().getBytes();
		int[] kk = new int[1 << m];
		for (int i = 1; i < n; i++) {
			int a = cc[i - 1] - 'a';
			int b = cc[i] - 'a';
			kk[1 << a | 1 << b]++;
		}
		for (int h = 0; h < m; h++)
			for (int b = 0; b < 1 << m; b++)
				if ((b & 1 << h) == 0)
					kk[b | 1 << h] += kk[b];
		int[] dp = new int[1 << m];
		int m_ = (1 << m) - 1;
		for (int b = 1; b < 1 << m; b++) {
			int k = n - 1 - kk[b] - kk[m_ ^ b];
			int x = INF;
			for (int h = 0; h < m; h++)
				if ((b & 1 << h) != 0) {
					int b_ = b ^ 1 << h;
					x = Math.min(x, dp[b_]);
				}
			dp[b] = x == INF ? INF : x + k;
		}
		println(dp[m_]);
	}
}


import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;

public class E {

	public static void main(String[] args) throws Exception {
		FastScanner sc = new FastScanner(System.in);
		FastPrinter out = new FastPrinter(System.out);
		E runner = new E();
		runner.run(sc, out);
		out.close();
	}

	int N, L;
	long[][] mat;
	long[] dp;

	public void run(FastScanner sc, FastPrinter out) throws Exception {
		L = sc.nextInt();
		N = sc.nextInt();
		mat = new long[N][N];
		char[] arr = sc.next().toCharArray();
		for (int i = 0; i < L - 1; i++) {
			int cur = arr[i] - 'a';
			int next = arr[i + 1] - 'a';
			if (cur != next) {
				mat[cur][next]++;
				mat[next][cur]++;
			}
		}
		dp = new long[1 << N];
		Arrays.fill(dp, -1);
		dp[(1 << N) - 1] = 0;
		long ans = solve(0);
		out.println(ans);
	}

	private long solve(int mask) {
		if (dp[mask] == -1) {
			long value = 0;
			for (int i = 0; i < N; i++) {
				if ((mask & (1 << i)) == 0) {
					for (int j = 0; j < N; j++) {
						if ((mask & (1 << j)) != 0) {
							value += mat[i][j];
						}
					}
				}
			}
			long ans = Long.MAX_VALUE;
			for (int i = 0; i < N; i++) {
				if ((mask & (1 << i)) == 0) {
					long temp = solve(mask | 1 << i);
					if (temp < ans) {
						ans = temp;
					}
				}
			}
			ans += value;
			dp[mask] = ans;
		}
		return dp[mask];
	}

	public void shuffle(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			int r = (int) (Math.random() * arr.length);
			if (i != r) {
				arr[i] ^= arr[r];
				arr[r] ^= arr[i];
				arr[i] ^= arr[r];
			}
		}
	}

	static class FastScanner {
		final private int BUFFER_SIZE = 1 << 10;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public FastScanner() {
			this(System.in);
		}

		public FastScanner(InputStream stream) {
			din = new DataInputStream(stream);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public FastScanner(String fileName) throws IOException {
			Path p = Paths.get(fileName);
			buffer = Files.readAllBytes(p);
			bytesRead = buffer.length;
		}

		int[] nextIntArray(int N) throws IOException {
			int[] arr = new int[N];
			for (int i = 0; i < N; i++) {
				arr[i] = nextInt();
			}
			return arr;
		}

		String nextLine() throws IOException {
			int c = read();
			while (c != -1 && isEndline(c))
				c = read();
			if (c == -1) {
				return null;
			}
			StringBuilder res = new StringBuilder();
			do {
				if (c >= 0) {
					res.appendCodePoint(c);
				}
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		String next() throws Exception {
			int c = readOutSpaces();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		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 {
			if (din == null) {
				bufferPointer = 0;
				bytesRead = -1;
			} else {
				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++];
		}

		private int readOutSpaces() throws IOException {
			while (true) {
				if (bufferPointer == bytesRead) fillBuffer();
				int c = buffer[bufferPointer++];
				if (!isSpaceChar(c)) {
					return c;
				}
			}
		}

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

		public int[][] readGraph(int N, int M, boolean zeroIndexed, boolean bidirectional) throws Exception {
			int[][] adj = new int[N][];
			int[] numNodes = new int[N];
			int[][] input = new int[M][2];
			for (int i = 0; i < M; i++) {
				int a = nextInt();
				int b = nextInt();
				if (zeroIndexed) {
					a--;
					b--;
				}
				input[i][0] = a;
				input[i][1] = b;
				numNodes[a]++;
				if (bidirectional) numNodes[b]++;
			}
			for (int i = 0; i < N; i++) {
				adj[i] = new int[numNodes[i]];
				numNodes[i] = 0;
			}
			for (int i = 0; i < M; i++) {
				int a = input[i][0];
				int b = input[i][1];
				adj[a][numNodes[a]++] = b;
				if (bidirectional) adj[b][numNodes[b]++] = a;
			}
			return adj;
		}

		public int[][][] readWeightedGraph(int N, int M, boolean zeroIndexed, boolean bidirectional) throws Exception {
			int[][][] adj = new int[N][][];
			int[] numNodes = new int[N];
			int[][] input = new int[M][3];
			for (int i = 0; i < M; i++) {
				int a = nextInt();
				int b = nextInt();
				if (zeroIndexed) {
					a--;
					b--;
				}
				int d = nextInt();
				input[i][0] = a;
				input[i][1] = b;
				input[i][2] = d;
				numNodes[a]++;
				if (bidirectional) numNodes[b]++;
			}
			for (int i = 0; i < N; i++) {
				adj[i] = new int[numNodes[i]][2];
				numNodes[i] = 0;
			}
			for (int i = 0; i < M; i++) {
				int a = input[i][0];
				int b = input[i][1];
				int d = input[i][2];
				adj[a][numNodes[a]][0] = b;
				adj[a][numNodes[a]][1] = d;
				numNodes[a]++;
				if (bidirectional) {
					adj[b][numNodes[b]][0] = a;
					adj[b][numNodes[b]][1] = d;
					numNodes[b]++;
				}
			}
			return adj;
		}
	}

	static class FastPrinter {
		static final char ENDL = '\n';
		StringBuilder buf;
		PrintWriter pw;

		public FastPrinter(OutputStream stream) {
			buf = new StringBuilder();
			pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(stream)));
		}

		public FastPrinter(String fileName) throws Exception {
			buf = new StringBuilder();
			pw = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
		}

		public FastPrinter(StringBuilder buf) {
			this.buf = buf;
		}

		public void print(int a) {
			buf.append(a);
		}

		public void print(long a) {
			buf.append(a);
		}

		public void print(char a) {
			buf.append(a);
		}

		public void print(char[] a) {
			buf.append(a);
		}

		public void print(double a) {
			buf.append(a);
		}

		public void print(String a) {
			buf.append(a);
		}

		public void print(Object a) {
			buf.append(a.toString());
		}

		public void println() {
			buf.append(ENDL);
		}

		public void println(int a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(long a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(char a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(char[] a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(double a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(String a) {
			buf.append(a);
			buf.append(ENDL);
		}

		public void println(Object a) {
			buf.append(a.toString());
			buf.append(ENDL);
		}

		public void printf(String format, Object... args) {
			buf.append(String.format(format, args));
		}

		public void close() {
			pw.print(buf);
			pw.close();
		}

		public void flush() {
			pw.print(buf);
			pw.flush();
			buf.setLength(0);
		}

	}

}


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];
		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;
			for(int j=0;j<m;j++) {
				if((i&(1<<j))>0) {//第j个字母
					for(int k=0;k<m;k++) {
						if((i&(1<<k))==0) {
							v+=cnt[j][k];
						}
					}
				}
			}
			for(int j=0;j<m;j++) {
				if((i&(1<<j))>0) {
					dp[i]=Math.min(dp[i], dp[i-(1<<j)]+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());
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String args[])
	{
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),m=sc.nextInt();int g[]=new int[1<<m];
		StringBuffer s=new StringBuffer(sc.next());
		s=s.insert(0, 'A');
		int D=(1<<m)-1;
		for(int i=1;i<n;i++)
		{
			int x=s.charAt(i)-'a',y=s.charAt(i+1)-'a';
			if(x!=y)
				g[1<<x|1<<y]++;
		}
		for(int j=0;j<m;j++)
			for(int i=0;i<=D;i++)
				if((i>>j&1)!=0)
					g[i]+=g[i^1<<j];
		int f[]=new int[1<<m];
		Arrays.fill(f, Integer.MAX_VALUE/2);
		f[0]=0;
		for(int i=0;i<=D;i++)
			for(int j=0;j<m;j++)
				if((i>>j&1)==0)
					f[i|1<<j]=Math.min(f[i|1<<j], f[i]+g[D]-g[i]-g[D^i]);
		System.out.println(f[D]);
	}

}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n, m;
	char[] str;
	int[][] occs, cost;
	int[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		//where's my 420???? :(
		long tot = 0;
		for(int i = 0; i < 19000; i++) tot += i;
		System.err.println(tot);

		n = fs.nextInt(); m = fs.nextInt();
		byte[] str = fs.next().getBytes();
		int[] occs = new int[1<<m];
		for(int i = 0; i < n-1; i++) {
			int l1 = str[i] - 'a';
			int l2 = str[i+1] - 'a';
			occs[(1<<l1) | (1<<l2)]++;
			occs[(1<<l2) | (1<<l1)]++;
		}
		//cost[mask][v] = numPairs with v for some all bits on in mask
		int all = (1<<m)-1;
		cost = new int[m][1<<m];
		for(int i = 0; i < m; i++) {
			for(int mask = 1; mask < all; mask++) {
				if(((1<<i)&mask) > 0) continue;
				int lb = mask & (-mask);
				int trail = Integer.numberOfTrailingZeros(lb);
				int nmask = mask ^ lb;
				cost[i][mask] = cost[i][nmask]+occs[1<<i | 1<<trail];
			}
		}

		dp = new int[1<<m];
		for(int mask = dp.length-2; mask >= 0; mask--) {
			int addOn = 0;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				addOn += cost[nxt][mask];
			}
			int res = oo;
			for(int nxt = 0; nxt < m; nxt++) {
				if(((1<<nxt)&mask) > 0) continue;
				int ret = addOn+dp[mask | (1<<nxt)];
				res = min(res, ret);
			}
			dp[mask] = res;
		}

		System.out.println(dp[0]>>1);

		out.close();
	}

	int oo = (int)1e9;
	int min(int a, int b) {
		if(a < b) return a;
		return b;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class Main {
	static long mod = 1000000007;
	static int INF = 1000000000;
 	public static void main(String[] args){
		FastScanner scanner = new FastScanner();
		int n = scanner.nextInt();
		int m = scanner.nextInt();
		String s = scanner.next();
		int[][] cnt = new int[20][20];
		for(int i = 0; i < n-1; i++){
			cnt[s.charAt(i)-'a'][s.charAt(i+1)-'a']++;
			cnt[s.charAt(i+1)-'a'][s.charAt(i)-'a']++;
		}
		//dp[i]:= 文字列i(この中に同一文字は含まれない)を作った時のコストの最小値
		int[] dp = new int[(1<<m)];
		for(int i = 0; i < (1<<m); i++){
			dp[i] = INF;
		}
		dp[0] = 0;
		for(int i = 0; i < (1<<m); i++){
			int cost = 0;
			for(int j = 0; j < m; j++){
				if((i>>j & 1) == 0){
					for(int k = 0; k < m; k++){
						if((~i>>k & 1) == 0){
							cost += cnt[j][k];
						}
					}
				}
			}
			for(int j = 0; j < m; j++){
				dp[i|1<<j] = Math.min(dp[i|1<<j],dp[i]+cost);
			}
		}
		System.out.println(dp[(1<<m)-1]);
	}
	static class BIT{
		int n;
		int[] bit;
		public BIT(int n){
			this.n = n;
			bit = new int[n+1];
		}
		void add(int idx, int val){
			for(int i = idx+1; i <= n; i += i&(-i)) bit[i-1] += val;
		}
		int sum(int idx){
			int res = 0;
			for(int i = idx+1; i > 0; i -= i&(-i)) res += bit[i-1];
			return res;
		}
		int sum(int begin, int end){
			if(begin == 0) return sum(end);
			return sum(end)-sum(begin-1);
		}
	}
	static class Pair implements Comparable<Pair>{
    int first, second;
    Pair(int a, int b){
        first = a;
        second = b;
    }
    @Override
    public boolean equals(Object o){
        if (this == o) return true;
        if (!(o instanceof Pair)) return false;
        Pair p = (Pair) o;
        return first == p.first && second == p.second;
    }
    @Override
    public int compareTo(Pair p){
        return first == p.first ? second - p.second : first - p.first; //firstで昇順にソート
        //return (first == p.first ? second - p.second : first - p.first) * -1; //firstで降順にソート
        //return second == p.second ? first - p.first : second - p.second;//secondで昇順にソート
        //return (second == p.second ? first - p.first : second - p.second)*-1;//secondで降順にソート
		    //return first * 1.0 / second > p.first * 1.0 / p.second ? 1 : -1; // first/secondの昇順にソート
		    //return first * 1.0 / second < p.first * 1.0 / p.second ? 1 : -1; // first/secondの降順にソート
				//return second * 1.0 / first > p.second * 1.0 / p.first ? 1 : -1; // second/firstの昇順にソート
		    //return second * 1.0 / first < p.second * 1.0 / p.first ? 1 : -1; // second/firstの降順にソート
				//return Math.atan2(second, first) > Math.atan2(p.second, p.first) ? 1 : -1; // second/firstの昇順にソート
				//return first + second > p.first + p.second ? 1 : -1; //first+secondの昇順にソート
				//return first + second < p.first + p.second ? 1 : -1; //first+secondの降順にソート
				//return first - second < p.first - p.second ? 1 : -1; //first-secondの降順にソート
		}
  }

	private static class FastScanner {
		private final InputStream in = System.in;
		private final byte[] buffer = new byte[1024];
		private int ptr = 0;
		private int buflen = 0;
		private boolean hasNextByte() {
				if (ptr < buflen) {
						return true;
				}else{
						ptr = 0;
						try {
								buflen = in.read(buffer);
						} catch (IOException e) {
								e.printStackTrace();
						}
						if (buflen <= 0) {
								return false;
						}
				}
				return true;
		}
		private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
		private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
		public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
		public String next() {
				if (!hasNext()) throw new NoSuchElementException();
				StringBuilder sb = new StringBuilder();
				int b = readByte();
				while(isPrintableChar(b)) {
						sb.appendCodePoint(b);
						b = readByte();
				}
				return sb.toString();
		}
		public long nextLong() {
				if (!hasNext()) throw new NoSuchElementException();
				long n = 0;
				boolean minus = false;
				int b = readByte();
				if (b == '-') {
						minus = true;
						b = readByte();
				}
				if (b < '0' || '9' < b) {
						throw new NumberFormatException();
				}
				while(true){
						if ('0' <= b && b <= '9') {
								n *= 10;
								n += b - '0';
						}else if(b == -1 || !isPrintableChar(b)){
								return minus ? -n : n;
						}else{
								throw new NumberFormatException();
						}
						b = readByte();
				}
		}
		public int nextInt() {
				long nl = nextLong();
				if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
				return (int) nl;
		}
		public double nextDouble() { return Double.parseDouble(next());}
	}
}