/*
 -> Written by <-
   -----------
  |J_O_B_E_E_L|
  |___________|
  |    ___    |
  |   (^_^)   |
  |  /( | )\  |
  |____|_|____|
*/

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

public class Test {
    static PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException, InterruptedException {
        Scanner sc = new Scanner(System.in);
        int x=sc.nextInt();
        int [] arr=sc.nextIntArray(x);
        long sum=arr[x-1];
        int min=arr[x-1];
        for(int i=x-2;i>=0;i--){
                if(arr[i]<min || i+1<min) {
                    min=Math.min(i + 1, arr[i]);
                    sum += min;
                }

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

    static  class pair implements Comparable <pair>{
        int x,y;
        public pair(int x,int y){this.x=x; this.y=y;}

        public int compareTo(pair o) {
           if(y==o.y) return  x-o.x;
            return  y-o.y;
        }
        public String toString(){
            return  x+" "+y;
        }
    }

    static class Scanner {

        private InputStream in;
        private byte[] buffer = new byte[1024];
        private int curbuf;
        private int lenbuf;

        public Scanner(InputStream in) {
            this.in = in;
            this.curbuf = this.lenbuf = 0;
        }

        public boolean hasNextByte() {
            if (curbuf >= lenbuf) {
                curbuf = 0;
                try {
                    lenbuf = in.read(buffer);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return false;
            }
            return true;
        }

        private int readByte() {
            if (hasNextByte())
                return buffer[curbuf++];
            else
                return -1;
        }

        private boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private void skip() {
            while (hasNextByte() && isSpaceChar(buffer[curbuf]))
                curbuf++;
        }

        public boolean hasNext() {
            skip();
            return hasNextByte();
        }

        public String next() {
            if (!hasNext())
                throw new NoSuchElementException();
            StringBuilder sb = new StringBuilder();
            int b = readByte();
            while (!isSpaceChar(b)) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            if (!hasNext())
                throw new NoSuchElementException();
            int c = readByte();
            while (isSpaceChar(c))
                c = readByte();
            boolean minus = false;
            if (c == '-') {
                minus = true;
                c = readByte();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res = res * 10 + c - '0';
                c = readByte();
            } while (!isSpaceChar(c));
            return (minus) ? -res : res;
        }

        public long nextLong() {
            if (!hasNext())
                throw new NoSuchElementException();
            int c = readByte();
            while (isSpaceChar(c))
                c = readByte();
            boolean minus = false;
            if (c == '-') {
                minus = true;
                c = readByte();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res = res * 10 + c - '0';
                c = readByte();
            } while (!isSpaceChar(c));
            return (minus) ? -res : res;
        }

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

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

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

    }

}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws IOException {
		FastReader in = new FastReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt();
		int[] a = in.nextIntArray(n);
		long sum = 0;
		for (int i = n - 1; i > 0; --i) {

			if (a[i] > a[i - 1]) {
				sum += a[i];
			} else {
				sum += a[i];
				a[i - 1] = Math.max(0, a[i] - 1);
			}
		}
		if (n > 1) {
			if (a[0] < a[1]) {
				sum += a[0];
			} else {
				sum += Math.max(0, a[1] - 1);
			}
			out.println(sum);
		} else {
			out.println(1);
		}

		out.flush();
		out.close();

	}

	static class FastReader {
		StringTokenizer st;
		BufferedReader br;

		public FastReader(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public FastReader(FileReader fileReader) {
			br = new BufferedReader(fileReader);
		}

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

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

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

		public long[] nextIntLong(int n) throws IOException {
			long[] ret = new long[n];
			for (int i = 0; i < n; i++) {
				ret[i] = nextLong();
			}
			return ret;
		}

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

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

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

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

}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws IOException {
		FastReader in = new FastReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt();
		int[] a = in.nextIntArray(n);
		long sum = 0;
		for (int i = n - 1; i > 0; --i) {

			if (a[i] > a[i - 1]) {
				sum += a[i];
			} else {
				sum += a[i];
				a[i - 1] = Math.max(0, a[i] - 1);
			}
		}
		if (n > 1) {
			if (a[0] < a[1]) {
				sum += a[0];
			} else {
				sum += Math.max(0, a[1] - 1);
			}
			out.println(sum);
		} else {
			out.println(a[0]);
		}

		out.flush();
		out.close();

	}

	static class FastReader {
		StringTokenizer st;
		BufferedReader br;

		public FastReader(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public FastReader(FileReader fileReader) {
			br = new BufferedReader(fileReader);
		}

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

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

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

		public long[] nextIntLong(int n) throws IOException {
			long[] ret = new long[n];
			for (int i = 0; i < n; i++) {
				ret[i] = nextLong();
			}
			return ret;
		}

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

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

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

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

}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws IOException {
		FastReader in = new FastReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt();
		int[] a = in.nextIntArray(n);
		long sum = 0;
		for (int i = n - 1; i > 0; --i) {

			if (a[i] > a[i - 1]) {
				sum += a[i];
			} else {
				sum += a[i];
				a[i - 1] = Math.max(0, a[i] - 1);
			}
		}
		if (a[0] < a[1]) {
			sum += a[0];
		} else {
			sum += Math.max(0, a[1] - 1);
		}
		out.println(sum);
		out.flush();
		out.close();

	}

	static class FastReader {
		StringTokenizer st;
		BufferedReader br;

		public FastReader(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public FastReader(FileReader fileReader) {
			br = new BufferedReader(fileReader);
		}

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

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

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

		public long[] nextIntLong(int n) throws IOException {
			long[] ret = new long[n];
			for (int i = 0; i < n; i++) {
				ret[i] = nextLong();
			}
			return ret;
		}

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

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

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

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

}


import java.util.Scanner;

public class Main{

  public static void main(String[] args){

    Scanner sc = new Scanner(System.in);

    int len = sc.nextInt();
    int[] choco = new int[len];
    for (int i=0; i!=len; i+=1){
      choco[i] = sc.nextInt();
    }

    long count = choco[len-1];
    long refer = count;
    for (int i=len-2; i>=0; i-=1){
//      System.out.print(refer + " ");
      if (refer == 1){
        break;
      }
      if (choco[i] < refer){
        count += choco[i];
        refer = choco[i];
      }
      else{
        count += --refer;
      }
    }

    System.out.println(count);

  }
}


import java.util.Scanner;

public class Main{

  public static void main(String[] args){

    Scanner sc = new Scanner(System.in);

    int len = sc.nextInt();
    int[] choco = new int[len];
    for (int i=0; i!=len; i+=1){
      choco[i] = sc.nextInt();
    }

    int count = choco[len-1];
    int refer = count;
    for (int i=len-2; i>=0; i-=1){
      if (refer == 1){
        break;
      }
      if (choco[i] < refer){
        count += choco[i];
        refer = choco[i];
      }
      else{
        count += --refer;
      }
    }

    System.out.println(count);

  }
}


import java.util.Scanner;

public class Main{

  public static void main(String[] args){

    Scanner sc = new Scanner(System.in);

    int len = sc.nextInt();
    int[] choco = new int[len];
    for (int i=0; i!=len; i+=1){
      choco[i] = sc.nextInt();
    }

    int count = choco[len-1];
    int refer = count;
    for (int i=len-2; i>=0; i-=1){
      if (refer == 1){
        break;
      }
      if (choco[i] < refer){
        count += choco[i];
        refer = choco[i];
      }
      else{
        count +=
          refer-1;
        refer -= 1;
      }
    }

    System.out.println(count);

  }
}


import java.util.ArrayList;
import java.util.*;
public class d2548
{
	public static void main (String[] args)
	 {
		Scanner sc=new Scanner(System.in);
		int t,i;
		t=1;
		while(t>0)
		{
			t--;
			int n=sc.nextInt();
			int a[]=new int[n];
			for(i=0;i<n;i++)
				a[i]=sc.nextInt();
			long ans=a[n-1];
			for(i=n-2;i>=0;i--)
			{
				int p=Math.min(a[i],a[i+1]-1);
				if(p<=0)
					break;
				ans+=Math.min(a[i], a[i+1]-1);
				a[i]=p;

			}
			System.out.println(ans);
		}
	}
}


import java.util.ArrayList;
import java.util.*;
public class d2548
{
	public static void main (String[] args)
	 {
		Scanner sc=new Scanner(System.in);
		int t,i;
		t=1;
		while(t>0)
		{
			t--;
			int n=sc.nextInt();
			int a[]=new int[n];
			for(i=0;i<n;i++)
				a[i]=sc.nextInt();
			long ans=a[n-1];
			for(i=n-2;i>=0;i--)
			{
				if(Math.min(a[i],a[i+1]-1)<=0)
					break;
				ans+=Math.min(a[i], a[i+1]-1);

			}
			System.out.println(ans);
		}
	}
}


import java.util.ArrayList;
import java.util.*;
public class d2548
{
	public static void main (String[] args)
	 {
		Scanner sc=new Scanner(System.in);
		int t,i;
		t=1;
		while(t>0)
		{
			t--;
			int n=sc.nextInt();
			int a[]=new int[n];
			for(i=0;i<n;i++)
				a[i]=sc.nextInt();
			long ans=a[n-1];
			for(i=n-2;i>=0;i--)
			{
				ans+=Math.min(a[i], a[i+1]-1);
				if(Math.min(a[i],a[i+1]-1)==0)
					break;
			}
			System.out.println(ans);
		}
	}
}


public class Main {
    public static void main(String args[]) {

        Scanner ip = new Scanner(System.in);

        int n = ip.nextInt();
        int[] arr = new int[n];

        for(int i = 0; i < n; i++)
            arr[i] = ip.nextInt();

        int currMax = arr[n-1];
        int sum = currMax;

        for(int i = n-2; i >= 0; i--){
            currMax = Math.min(arr[i], currMax-1);
            sum += Math.max(0, currMax);
        }
        System.out.println(sum);
    }
}


import java.util.*;
public class Main {
    public static void main(String args[]) {

        Scanner ip = new Scanner(System.in);

        int n = ip.nextInt();
        int[] arr = new int[n];

        for(int i = 0; i < n; i++)
            arr[i] = ip.nextInt();

        int currMax = arr[n-1];
        int sum = currMax;

        for(int i = n-2; i >= 0; i--){
            if(arr[i] > currMax){
                if(currMax > 0)
                    currMax--;
                sum += currMax;
            }

            else if(arr[i] < currMax){
                currMax = arr[i];
                sum += currMax;
            }
            else{
                if(currMax > 0)
                    currMax--;
                sum += currMax;
            }
        }
        System.out.println(sum);
    }
}


import java.util.*;
public class Main {
    public static void main(String args[]) {

        Scanner ip = new Scanner(System.in);

        int n = ip.nextInt();
        long[] arr = new long[n];

        for(int i = 0; i < n; i++)
            arr[i] = ip.nextInt();

        long currMax = Long.MAX_VALUE;
        long sum = 0;

        for(int i = n-1; i >= 0; i--){
            currMax = Math.min(arr[i], currMax-1);
            sum += Math.max(0, currMax);
        }
        System.out.println(sum);
    }
}


import java.util.*;
public class Main {
    public static void main(String args[]) {

        Scanner ip = new Scanner(System.in);

        int n = ip.nextInt();
        int[] arr = new int[n];

        for(int i = 0; i < n; i++)
            arr[i] = ip.nextInt();

        int currMax = arr[n-1];
        int sum = currMax;

        for(int i = n-2; i >= 0; i--){
            currMax = Math.min(arr[i], currMax-1);
            sum += Math.max(0, currMax);
        }
        System.out.println(sum);
    }
}


import java.util.*;
public class Main {
    public static void main(String args[]) {

        Scanner ip = new Scanner(System.in);

        int n = ip.nextInt();
        int[] arr = new int[n];

        for(int i = 0; i < n; i++)
            arr[i] = ip.nextInt();

        int currMax = Integer.MAX_VALUE;
        int sum = 0;

        for(int i = n-1; i >= 0; i--){
            currMax = Math.min(arr[i], currMax-1);
            sum += Math.max(0, currMax);
        }
        System.out.println(sum);
    }
}


import java.util.Scanner;

/**
 *
 * @author Akhilesh
 */
public class Chocolates1139B {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int n = scan.nextInt();
        int arr[] = new int[n];

        for(int i = 0; i < n; i++){
            arr[i] = scan.nextInt();
        }

        int max = arr[n-1];

        for(int i = n-2; i >= 0; i--){
            if(arr[i+1] == 0 || arr[i+1] == 1){
                break;
            }

            arr[i] = arr[i+1] > arr[i] ? arr[i] : arr[i+1]-1;

            max += arr[i];
        }

        System.out.println(max);
    }
}


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
//package Practice_1100;

import java.io.*;

/**
 *
 * @author Akhilesh
 */
public class B1139 {
    public static void main(String[] args) throws IOException {
        BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(scan.readLine().trim());

        int arr[] = new int[n];
        String str[] = scan.readLine().split("\\s+");
        for(int i = 0; i < n; i++){
            arr[i] = Integer.parseInt(str[i]);
        }

        long max = arr[n-1], add = arr[n-1];

        for(int i = n-2; i >= 0; i--){
            add = Math.max(Math.min(arr[i], add - 1), 0);
            max += add;
        }

        System.out.println(max);
    }
}


import java.util.Scanner;

/**
 *
 * @author Akhilesh
 */
public class Chocolates1139B {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int n = scan.nextInt();
        int arr[] = new int[n];

        for(int i = 0; i < n; i++){
            arr[i] = scan.nextInt();
        }

        int max = arr[n-1];

        for(int i = n-2; i >= 0; i--){
            if(arr[i] < arr[i+1])
                max += arr[i];
            else{
                if(arr[i + 1] - 1 >= 0)
                    arr[i] = arr[i + 1] - 1;
                else
                    arr[i] = 0;

                max += arr[i];
            }
        }

        System.out.println(max);
    }
}


import java.util.Scanner;

/**
 *
 * @author Akhilesh
 */
public class Chocolates1139B {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int n = scan.nextInt();
        int arr[] = new int[n];

        for(int i = 0; i < n; i++){
            arr[i] = scan.nextInt();
        }

        int max = arr[n-1];

        for(int i = n-2; i >= 0; i--){
            if(arr[i+1] == 1)
                break;

            arr[i] = Math.min(arr[i], arr[i+1]-1);

            max += arr[i];
        }

        System.out.println(max);
    }
}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   int count = arrr[n-1];
	           for (int i = n-1; i>=1; i--) {

                    int val= Math.min(arrr[i-1], arrr[i]-1);
                    if(val<0)  arrr[i-1]= 0;
                    else arrr[i-1]= val;
                    count+=arrr[i-1];
            }
	           System.out.println(count);

	}

}


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

public class SegmentTreeRMQ
{
	int st[];

	int minVal(int x, int y) {
		return (x < y) ? x : y;
	}

	int getMid(int s, int e) {
		return s + (e - s) / 2;
	}

	int RMQUtil(int ss, int se, int qs, int qe, int index)
	{

		if (qs <= ss && qe >= se)
			return st[index];

		if (se < qs || ss > qe)
			return Integer.MAX_VALUE;

		int mid = getMid(ss, se);
		return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
				RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
	}

	int RMQ(int n, int qs, int qe)
	{
		if (qs < 0 || qe > n - 1 || qs > qe) {
			System.out.println("Invalid Input");
			return -1;
		}

		return RMQUtil(0, n - 1, qs, qe, 0);
	}

	int constructSTUtil(int arr[], int ss, int se, int si)
	{

		if (ss == se) {
			st[si] = arr[ss];
			return arr[ss];
		}

		int mid = getMid(ss, se);
		st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
				constructSTUtil(arr, mid + 1, se, si * 2 + 2));
		return st[si];
	}

	void constructST(int arr[], int n)
	{
		int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

		int max_size = 2 * (int) Math.pow(2, x) - 1;
		st = new int[max_size];
		constructSTUtil(arr, 0, n - 1, 0);
	}

	public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n+1];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }

		SegmentTreeRMQ tree = new SegmentTreeRMQ();

                  arrr[n]= Integer.MAX_VALUE;
		tree.constructST(arrr, n+1);

                               int count= 0 ;

            int out [] = new int[n];
            for (int i = 0; i < n; i++) {

                   int min = tree.RMQ(n+1, i+1, n);
                   int diff;
                   if(min<arrr[i]) diff=min-1;
                   else if (min>arrr[i]) diff = arrr[i];
                   else  diff = min -1;
                  // System.out.println(diff);
                   if(diff<1) diff=0;
                    out[i] = diff;

  // 3                          0 0 0 1 2 3 4 5 6 7 8
            }
        // System.out.println(Arrays.toString(out));
            for (int i = n-1; i >=1; i--) {
                int val=0;
                if(out[i-1]>=out[i]) val = Math.abs(out[i-1]-out[i])+1;
                else continue;
                if( out[i-1]-val<0) out[i-1] = 0;
                else out[i-1] = out[i-1]-val;

            }
            for (int i = 0; i < n; i++) count+=out[i];

            //System.out.println(Arrays.toString(out));
            System.out.println(count+out[0]);

	}
}


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

public class SegmentTreeRMQ
{
	int st[];

	int minVal(int x, int y) {
		return (x < y) ? x : y;
	}

	int getMid(int s, int e) {
		return s + (e - s) / 2;
	}

	int RMQUtil(int ss, int se, int qs, int qe, int index)
	{

		if (qs <= ss && qe >= se)
			return st[index];

		if (se < qs || ss > qe)
			return Integer.MAX_VALUE;

		int mid = getMid(ss, se);
		return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
				RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
	}

	int RMQ(int n, int qs, int qe)
	{
		if (qs < 0 || qe > n - 1 || qs > qe) {
			System.out.println("Invalid Input");
			return -1;
		}

		return RMQUtil(0, n - 1, qs, qe, 0);
	}

	int constructSTUtil(int arr[], int ss, int se, int si)
	{

		if (ss == se) {
			st[si] = arr[ss];
			return arr[ss];
		}

		int mid = getMid(ss, se);
		st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
				constructSTUtil(arr, mid + 1, se, si * 2 + 2));
		return st[si];
	}

	void constructST(int arr[], int n)
	{
		int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

		int max_size = 2 * (int) Math.pow(2, x) - 1;
		st = new int[max_size];
		constructSTUtil(arr, 0, n - 1, 0);
	}

	public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n+1];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }

		SegmentTreeRMQ tree = new SegmentTreeRMQ();

                  arrr[n]= Integer.MAX_VALUE;
		tree.constructST(arrr, n+1);

                               int count= 0 ;

            int out [] = new int[n];
            for (int i = 0; i < n; i++) {

                   int min = tree.RMQ(n+1, i+1, n);
                   int diff;
                   if(min<arrr[i]) diff=min-1;
                   else if (min>arrr[i]) diff = arrr[i];
                   else  diff = min -1;
                  // System.out.println(diff);
                   if(diff<1) diff=0;
                    out[i] = diff;

  // 3                          0 0 0 1 2 3 4 5 6 7 8
            }
        // System.out.println(Arrays.toString(out));
            for (int i = n-1; i >=1; i--) {
                int val=0;
                if(out[i-1]>=out[i]) val = Math.abs(out[i-1]-out[i])+1;
                else continue;
                if( out[i-1]-val<0) out[i-1] = 0;
                else out[i-1] = out[i-1]-val;

            }
            for (int i = 0; i < n; i++) count+=out[i];

            System.out.println(Arrays.toString(out));
            System.out.println(count);

	}
}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   int count = arrr[n-1];

                   int max = arrr[n-1];
	           for (int i = n-1; i>=1; i--) {

                    int val= Math.min(max-1, arrr[i-1]);
                    if(val<=0) max=0;
                    else max = val;
                    count+= max;

            }
	           System.out.println(count);

	}

}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   int count = 0;

                   int max = Integer.MAX_VALUE;
	           for (int i = n-1; i>=1; i--) {

                    max= Math.max(0, Math.min(max-1, arrr[i]));

                    count+= max;

            }
	           System.out.println(count);

	}

}


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

public class SegmentTreeRMQ
{
	int st[];

	int minVal(int x, int y) {
		return (x < y) ? x : y;
	}

	int getMid(int s, int e) {
		return s + (e - s) / 2;
	}

	int RMQUtil(int ss, int se, int qs, int qe, int index)
	{

		if (qs <= ss && qe >= se)
			return st[index];

		if (se < qs || ss > qe)
			return Integer.MAX_VALUE;

		int mid = getMid(ss, se);
		return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
				RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
	}

	int RMQ(int n, int qs, int qe)
	{
		if (qs < 0 || qe > n - 1 || qs > qe) {
			System.out.println("Invalid Input");
			return -1;
		}

		return RMQUtil(0, n - 1, qs, qe, 0);
	}

	int constructSTUtil(int arr[], int ss, int se, int si)
	{

		if (ss == se) {
			st[si] = arr[ss];
			return arr[ss];
		}

		int mid = getMid(ss, se);
		st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
				constructSTUtil(arr, mid + 1, se, si * 2 + 2));
		return st[si];
	}

	void constructST(int arr[], int n)
	{
		int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

		int max_size = 2 * (int) Math.pow(2, x) - 1;
		st = new int[max_size];
		constructSTUtil(arr, 0, n - 1, 0);
	}

	public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n+1];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }

		SegmentTreeRMQ tree = new SegmentTreeRMQ();

                  arrr[n]= Integer.MAX_VALUE;
		tree.constructST(arrr, n+1);

                               int count= 0 ;

            int out [] = new int[n];
            for (int i = 0; i < n; i++) {

                   int min = tree.RMQ(n+1, i+1, n);
                   int diff;
                   if(min<arrr[i]) diff=min-1;
                   else if (min>arrr[i]) diff = arrr[i];
                   else  diff = min -1;
                  // System.out.println(diff);
                   if(diff<1) diff=0;
                    out[i] = diff;

  // 3                          0 0 0 1 2 3 4 5 6 7 8
            }
        // System.out.println(Arrays.toString(out));
            for (int i = n-1; i >=1; i--) {
                int val=0;
                if(out[i-1]>=out[i]) val = Math.abs(out[i-1]-out[i])+1;
                else continue;
                if( out[i-1]-val<0) out[i-1] = 0;
                else out[i-1] = out[i-1]-val;

            }
            for (int i = 0; i < n; i++) count+=out[i];

            System.out.println(count);

	}
}


import java.util.Scanner;

public class SegmentTreeRMQ
{
	int st[];

	int minVal(int x, int y) {
		return (x < y) ? x : y;
	}

	int getMid(int s, int e) {
		return s + (e - s) / 2;
	}

	int RMQUtil(int ss, int se, int qs, int qe, int index)
	{

		if (qs <= ss && qe >= se)
			return st[index];

		if (se < qs || ss > qe)
			return Integer.MAX_VALUE;

		int mid = getMid(ss, se);
		return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
				RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
	}

	int RMQ(int n, int qs, int qe)
	{
		if (qs < 0 || qe > n - 1 || qs > qe) {
			System.out.println("Invalid Input");
			return -1;
		}

		return RMQUtil(0, n - 1, qs, qe, 0);
	}

	int constructSTUtil(int arr[], int ss, int se, int si)
	{

		if (ss == se) {
			st[si] = arr[ss];
			return arr[ss];
		}

		int mid = getMid(ss, se);
		st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
				constructSTUtil(arr, mid + 1, se, si * 2 + 2));
		return st[si];
	}

	void constructST(int arr[], int n)
	{
		int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

		int max_size = 2 * (int) Math.pow(2, x) - 1;
		st = new int[max_size];
		constructSTUtil(arr, 0, n - 1, 0);
	}

	public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n+1];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }

		SegmentTreeRMQ tree = new SegmentTreeRMQ();

                  arrr[n]= Integer.MAX_VALUE;
		tree.constructST(arrr, n+1);

                               int count= 0 ;

                               System.out.println("");
            for (int i = 0; i < n; i++) {

                   int min = tree.RMQ(n+1, i+1, n);
                   int diff;
                   if(min<arrr[i]) diff=min-1;
                   else if (min>arrr[i]) diff = arrr[i];
                   else  diff = min -1;

                   if(diff<1) continue;

                    count +=diff;

            }

            System.out.println(count);

	}
}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   int count = arrr[n-1];

                   int max = arrr[n-1];
	           for (int i = n-1; i>=0; i--) {

                    int val= Math.min(max-1, arrr[i]);
                    if(val<=0) max=0;
                    else max = val;
                    count+= max;

            }
	           System.out.println(count);

	}

}


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

public class SegmentTreeRMQ
{
	int st[];

	int minVal(int x, int y) {
		return (x < y) ? x : y;
	}

	int getMid(int s, int e) {
		return s + (e - s) / 2;
	}

	int RMQUtil(int ss, int se, int qs, int qe, int index)
	{

		if (qs <= ss && qe >= se)
			return st[index];

		if (se < qs || ss > qe)
			return Integer.MAX_VALUE;

		int mid = getMid(ss, se);
		return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
				RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
	}

	int RMQ(int n, int qs, int qe)
	{
		if (qs < 0 || qe > n - 1 || qs > qe) {
			System.out.println("Invalid Input");
			return -1;
		}

		return RMQUtil(0, n - 1, qs, qe, 0);
	}

	int constructSTUtil(int arr[], int ss, int se, int si)
	{

		if (ss == se) {
			st[si] = arr[ss];
			return arr[ss];
		}

		int mid = getMid(ss, se);
		st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
				constructSTUtil(arr, mid + 1, se, si * 2 + 2));
		return st[si];
	}

	void constructST(int arr[], int n)
	{
		int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

		int max_size = 2 * (int) Math.pow(2, x) - 1;
		st = new int[max_size];
		constructSTUtil(arr, 0, n - 1, 0);
	}

	public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n+1];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }

		SegmentTreeRMQ tree = new SegmentTreeRMQ();

                  arrr[n]= Integer.MAX_VALUE;
		tree.constructST(arrr, n+1);

                               int count= 0 ;

            long out [] = new long[n];
            for (int i = 0; i < n; i++) {

                   int min = tree.RMQ(n+1, i+1, n);
                   int diff;
                   if(min<arrr[i]) diff=min-1;
                   else if (min>arrr[i]) diff = arrr[i];
                   else  diff = min -1;
                  // System.out.println(diff);
                   if(diff<1) diff=0;
                    out[i] = diff;

  // 3                          0 0 0 1 2 3 4 5 6 7 8
            }
        // System.out.println(Arrays.toString(out));
            for (int i = n-1; i >=1; i--) {
                int val=0;
                if(out[i-1]>=out[i]) val = Math.abs(out[i-1]-out[i])+1;
                else continue;
                if( out[i-1]-val<0) out[i-1] = 0;
                else out[i-1] = out[i-1]-val;

            }
            for (int i = 0; i < n; i++) count+=out[i];

            System.out.println(count);

	}
}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   long count = arrr[n-1];

                   int max = arrr[n-1];
	           for (int i = n-1; i>=1; i--) {

                    int val= Math.min(max-1, arrr[i-1]);
                    if(val<=0) max=0;
                    else max = val;
                    count+= max;

            }
	           System.out.println(count);

	}

}


import java.util.Scanner;

public class Main{
public static void main(String args[])
	{

                Scanner read = new Scanner(System.in);
                int n = read.nextInt();

                int arrr[] = new int[n];
                for (int i = 0; i < n; i++) {
                    arrr[i]= read.nextInt();

            }
                   int count = 0;

                   int max = Integer.MAX_VALUE;
	           for (int i = n-1; i>=0; i--) {

                    max= Math.max(0, Math.min(max-1, arrr[i]));

                    count+= max;

            }
	           System.out.println(count);

	}

}


import java.util.*;
public class df
{
    public static void main(String []args)
    {
        Scanner in=new Scanner(System.in);
        final int n=in.nextInt();
        final long a[]=new long[n];
        long res[]=new long[n];

        int i,j,x=0;
        long sum=0;
        for(i=0;i<n;i++)
           a[i]=in.nextInt();
        res[n-1]=a[n-1];
        for(i=n-2;i>=0;i--)
        {
            if(a[i]>=res[i+1])
                res[i]=res[i+1]-1;
            else
                res[i]=a[i];
        }
        for(i=0;i<n;i++)
        {
            System.out.print(res[i]+" ");
            if(res[i]>0)
                sum=sum+res[i];
        }
        System.out.println();
        System.out.println(sum);
    }
}


import java.util.*;
public class df
{
    public static void main(String []args)
    {
        Scanner in=new Scanner(System.in);
        final int n=in.nextInt();
        final long a[]=new long[n];
        long res[]=new long[n];

        int i,j,x=0;
        long sum=0;
        for(i=0;i<n;i++)
           a[i]=in.nextInt();
        res[n-1]=a[n-1];
        for(i=n-2;i>=0;i--)
        {
            if(a[i]>=res[i+1])
                res[i]=res[i+1]-1;
            else
                res[i]=a[i];
        }
        for(i=0;i<n;i++)
        {
            //System.out.print(res[i]+" ");
            if(res[i]>0)
                sum=sum+res[i];
        }
        //System.out.println();
        System.out.println(sum);
    }
}


import java.util.*;
public class df
{
    public static void main(String []args)
    {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int a[]=new int[n];
        int res[]=new int[n];

        int i,j,x=0,sum=0;
        for(i=0;i<n;i++)
           a[i]=in.nextInt();
        res[n-1]=a[n-1];
        for(i=n-2;i>=0;i--)
        {
            x=a[i];
            for(j=i+1;j<n;j++)
            {
                if(res[j]<=x)
                    x=res[j]-1;;
            }
            if(x>=0)
                res[i]=x;
        }
        for(i=0;i<n;i++)
        {
           // System.out.print(res[i]+" ");
            sum=sum+res[i];
        }
        //System.out.println();
        System.out.println(sum);
    }
}


import java.util.*;
public class df
{
    public static void main(String []args)
    {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        final int a[]=new int[n];
        int i,j,x=0,sum=0;
        for(i=0;i<n;i++)
           a[i]=in.nextInt();
        for(i=0;i<n;i++)
        {
            x=a[i];
            for(j=i+1;j<n;j++)
            {
                if(a[j]<=x)
                    x=a[j]-1;;
            }
            sum=sum+x;
        }
        System.out.println(sum);
    }
}


import java.util.*;
public class df
{
    public static void main(String []args)
    {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int a[]=new int[n];
        int res[]=new int[n];

        int i,j,x=0,sum=0;
        for(i=0;i<n;i++)
           a[i]=in.nextInt();
        res[n-1]=a[n-1];
        for(i=n-2;i>0;i--)
        {
            x=a[i];
            for(j=i+1;j<n;j++)
            {
                if(res[j]<=x)
                    x=res[j]-1;;
            }
            if(x>=0)
                res[i]=x;
        }
        for(i=0;i<n;i++)
        {
            //System.out.print(res[i]+" ");
            sum=sum+res[i];
        }
        //System.out.println();
        System.out.println(sum);
    }
}


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define pub(x) push_back(x)
#define x first
#define y second
#define MP make_pair
typedef long long ll;
typedef pair<int,string> two;
typedef long double real;
typedef pair<int,int> where;
bool better(const two &a, const two &b)
{
	if (a.x != b.x) return a.x < b.x;
	return a.y < b.y;
}
const int dr[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
const int INF = 10000000;
queue<where> q;
where st, en ;
two d[55][55];
char s[55][55];
int n, m;

two work(char p0 = '.', char p1 = '.', char p2 = '.', char p3 = '.')
{
	two ret = MP(INF, "");
	for (int i = 1; i <= n; ++i)
	for (int j = 1; j <= m; ++j)
		d[i][j] = MP(INF, "");
	q.push(st);
	d[st.x][st.y] = MP(0, "");
	//printf("# %c %c %c %c #\n", p0, p1, p2, p3);
	//printf("%d %d\n", n, m);
	while (!q.empty())
	{
		where c = q.front(); q.pop();
		//printf(" < %d %d >\n", c.x, c.y);
		if (c.x == en.x && c.y == en.y) continue;
		for (int k = 0; k < 4; ++k)
		{
			int a = c.x + dr[k][0], b = c.y + dr[k][1];
			//printf("%d %d %c\n", a, b, s[a][b]);
			//if (s[a][b] == 'T' || s[a][b] == p0 || s[a][b] == p1 || s[a][b] == p2 || s[a][b] == p3) puts("hehe");
			//if (a > 0 && a <= n && b > 0 && b <= m)puts("nima");
			if (a > 0 && a <= n && b > 0 && b <= m)
			if (s[a][b] == 'T' || s[a][b] == p0 || s[a][b] == p1 || s[a][b] == p2 || s[a][b] == p3)
			{
				two tmp = MP(d[c.x][c.y].x + 1, d[c.x][c.y].y);
				if (s[a][b] != 'T') tmp.y += s[a][b];
				//printf("tmp: %d %s", tmp.x, tmp.y.c_str());
				if (better(tmp, d[a][b]))
				{
					d[a][b] = tmp;
					q.push(MP(a, b));
				}
			}
		}
	}
	return d[en.x][en.y];
}

bool et[200]= {0};
int main()
{
	int kk;scanf("%d%d%d", &n, &m, &kk);
	for (int i = 1; i <= n; ++i)
		scanf("%s", s[i] + 1);

	for (int i = 1; i <= n; ++i)
	for (int j = 1; j <= m; ++j)
	{
		if (s[i][j] == 'S') st = MP(i,j);
		if (s[i][j] == 'T') en = MP(i,j);
		et[s[i][j]] = true;
	}
	int all = 0;
	for (char c = 'a'; c <= 'z' ; ++c)
		if (et[c]) ++all;
	if (all < kk) kk = all;
	two ans = MP(INF, string(""));
	for (char a = 'a'; a <= 'z'; ++a) if (et[a])
	{
		if (kk == 1)
		{
			two now = work(a);
			if (better(now, ans))
				ans = now;
		} else
		for (char b = a+1; b <='z'; ++b) if (et[b])
		{
			if (kk == 2)
			{
				//printf("!! %c %c !!\n", a, b);
				two now = work(a, b);
				if (better(now, ans))
					ans = now;
			} else
			for (char c = b+1; c <= 'z'; ++c) if (et[c])
			{
				if (kk == 3)
				{
					two now = work(a, b, c);
					if (better(now, ans))
						ans = now;
				} else
				for (char d = c+1; d <= 'z'; ++d) if (et[d])
				{
					two now = work(a, b, c, d);
					if (better(now, ans))
						ans = now;
				}
			}
		}
	}
	//printf("%d\n", ans.x);
	if (ans.x < INF)
		puts(ans.y.c_str());
		else puts("-1");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define pub(x) push_back(x)
#define x first
#define y second
#define MP make_pair
typedef long long ll;
typedef pair<int,string> two;
typedef long double real;
typedef pair<int,int> where;
bool better(const two &a, const two &b)
{
	if (a.x != b.x) return a.x < b.x;
	return a.y < b.y;
}
const int dr[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
const int INF = 10000000;
queue<where> q;
where st, en;
int d[55][55];
char s[55][55];
int n, m;

two work(char p0 = '.', char p1 = '.', char p2 = '.', char p3 = '.')
{
	memset(d, 63, sizeof d);
	q.push(st);
	d[st.x][st.y] = 0;
	vector<pair<char, int> > v;
	while (!q.empty())
	{
		where c = q.front(); q.pop();
		v.clear();
		if (c.x == en.x && c.y == en.y) break;
		for (int k = 0; k < 4; ++k)
		{
			int a = c.x + dr[k][0], b = c.y + dr[k][1];
			if (a > 0 && a <= n && b > 0 && b <= m)
			if (s[a][b] == 'S' || s[a][b] == p0 || s[a][b] == p1 || s[a][b] == p2 || s[a][b] == p3)
			if (d[c.x][c.y] + 1 < d[a][b])
			{
				d[a][b] = d[c.x][c.y] + 1;
				q.push(MP(a,b));
			}
		}
	}
	if (d[en.x][en.y] < INF - 1)
	{
		two ret = MP(d[en.x][en.y], "");
		where p = en;
		while (p.x != st.x || p.y != st.y)
		{
			v.clear();
			for (int k = 0; k < 4; ++k)
			{
				int a = p.x + dr[k][0], b = p.y + dr[k][1];
				if (a > 0 && a <= n && b > 0 && b <= m)
				if (s[a][b] == 'T' || s[a][b] == p0 || s[a][b] == p1 || s[a][b] == p2 || s[a][b] == p3)
				if (d[a][b] == d[p.x][p.y] - 1)
					v.pub(MP(s[a][b], k));
			}
			sort(v.begin(), v.end());
			int a = p.x + dr[v[0].y][0], b = p.y + dr[v[0].y][1];
			if (s[a][b] != 'T')
				ret.y += s[a][b];
			p = MP(a,b);
		}

		return ret;

	}
	else return MP(INF, "");
}

bool et[200]= {0};
int main()
{
	int kk;scanf("%d%d%d", &n, &m, &kk);
	if (n * m == 2) return 0;
	for (int i = 1; i <= n; ++i)
		scanf("%s", s[i] + 1);

	for (int i = 1; i <= n; ++i)
	for (int j = 1; j <= m; ++j)
	{
		if (s[i][j] == 'S') st = MP(i,j);
		if (s[i][j] == 'T') en = MP(i,j);
		et[s[i][j]] = true;
	}
	swap(st, en);
	int all = 0;
	for (char c = 'a'; c <= 'z' ; ++c)
		if (et[c]) ++all;
	if (all < kk) kk = all;
	two ans = MP(INF, string(""));
	for (char a = 'a'; a <= 'z'; ++a) if (et[a])
	{
		if (kk == 1)
		{
			two now = work(a);
			if (better(now, ans))
				ans = now;
		} else
		for (char b = a+1; b <='z'; ++b) if (et[b])
		{
			if (kk == 2)
			{
				two now = work(a, b);
				if (better(now, ans))
					ans = now;
			} else
			for (char c = b+1; c <= 'z'; ++c) if (et[c])
			{
				if (kk == 3)
				{
					two now = work(a, b, c);
					if (better(now, ans))
						ans = now;
				} else
				for (char d = c+1; d <= 'z'; ++d) if (et[d])
				{
					two now = work(a, b, c, d);
					if (better(now, ans))
						ans = now;
				}
			}
		}
	}
	//printf("%d\n", ans.x);
	if (ans.x < INF -1)
		puts(ans.y.c_str());
		else puts("-1");
	return 0;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

const int Fx[]={0,0,1,-1};
const int Fy[]={1,-1,0,0};

int N,M,K,TotHave;
char Map[60][60];
char CanUsed[15000][5];
int Tot,Sx,Sy,Tx,Ty;
char Tmp[5];
bool HAVE[300];
bool Vis[60][60];
int Qx[60*60],Qy[60*60];
int D[60][60];
string Path[60][60];

void DFS(int dep)
{
	if (dep>K)
	{
		++Tot;
		memcpy(CanUsed[Tot],Tmp,sizeof(Tmp));
		return ;
	}
	for (char x=Tmp[dep-1]+1;x<='z';++x)
		if (HAVE[x])
		{
			Tmp[dep]=x;
			HAVE[x]=false;
			DFS(dep+1);
			HAVE[x]=true;
		}
}

int main()
{
//	freopen("a.in","r",stdin);
	scanf("%d%d%d",&N,&M,&K);
	for (int i=1;i<=N;++i)
		scanf("%s",Map[i]+1);
	for (int i=1;i<=N;++i)
		for (int j=1;j<=M;++j)
		{
			if (!HAVE[Map[i][j]])	++TotHave;
			HAVE[Map[i][j]]=true;
			if (Map[i][j]=='S')
			{	Sx=i;Sy=j;	}
			if (Map[i][j]=='T')
			{	Tx=i;Ty=j;	}
		}
	K=min(K,TotHave-2);
	Tmp[0]='a'-1;
	DFS(1);
	int FAns=9999999;
	string SAns="-1 ";
	for (int i=1;i<=Tot;++i)
	{
		memset(HAVE,0,sizeof(HAVE));
		for (int j=1;j<=K;++j)
			HAVE[CanUsed[i][j]]=1;
		HAVE['S']=HAVE['T']=1;
		memset(D,63,sizeof(D));
		memset(Vis,0,sizeof(Vis));
		Path[Sx][Sy]="";
		D[Sx][Sy]=0;
		Qx[1]=Sx;Qy[1]=Sy;

		int S=0,E=1,X,Y;
		while (S<E)
		{
			++S;
			X=Qx[S];Y=Qy[S];

			for (int f=0;f<4;++f)
				if (HAVE[Map[X+Fx[f]][Y+Fy[f]]] &&
						(D[X+Fx[f]][Y+Fy[f]]>D[X][Y]+1||
						(D[X+Fx[f]][Y+Fy[f]]==D[X][Y]+1&&Path[X+Fx[f]][Y+Fy[f]]>Path[X][Y]+Map[X+Fx[f]][Y+Fy[f]])))
				{
					D[X+Fx[f]][Y+Fy[f]]=D[X][Y]+1;
					Path[X+Fx[f]][Y+Fy[f]]=Path[X][Y]+Map[X+Fx[f]][Y+Fy[f]];
					if (!Vis[X+Fx[f]][Y+Fy[f]])
					{
						Vis[X+Fx[f]][Y+Fy[f]]=true;
						++E;
						Qx[E]=X+Fx[f];
						Qy[E]=Y+Fy[f];
					}
				}
		}
		if (FAns>D[Tx][Ty]||(FAns==D[Tx][Ty]&&SAns>Path[Tx][Ty]))
		{
			FAns=D[Tx][Ty];
			SAns=Path[Tx][Ty];
		}
	}
	for (int i=0;i<SAns.size()-1;++i)
		cout<<SAns[i];
	cout<<endl;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

const int Fx[]={0,0,1,-1};
const int Fy[]={1,-1,0,0};

int N,M,K,TotHave;
char Map[60][60];
char CanUsed[15000][5];
int Tot,Sx,Sy,Tx,Ty;
char Tmp[5];
bool HAVE[300];
bool Vis[60][60];
int Qx[60*60],Qy[60*60];
int D[60][60];
string Path[60][60];

void DFS(int dep)
{
	if (dep>K)
	{
		++Tot;
		memcpy(CanUsed[Tot],Tmp,sizeof(Tmp));
		return ;
	}
	for (char x=Tmp[dep-1]+1;x<='z';++x)
		if (HAVE[x])
		{
			Tmp[dep]=x;
			HAVE[x]=false;
			DFS(dep+1);
			HAVE[x]=true;
		}
}

int main()
{
	freopen("a.in","r",stdin);
	scanf("%d%d%d",&N,&M,&K);
	for (int i=1;i<=N;++i)
		scanf("%s",Map[i]+1);
	for (int i=1;i<=N;++i)
		for (int j=1;j<=M;++j)
		{
			if (!HAVE[Map[i][j]])	++TotHave;
			HAVE[Map[i][j]]=true;
			if (Map[i][j]=='S')
			{	Sx=i;Sy=j;	}
			if (Map[i][j]=='T')
			{	Tx=i;Ty=j;	}
		}
	K=min(K,TotHave-2);
	Tmp[0]='a'-1;
	DFS(1);
	int FAns=99999999;
	string SAns="-1 ";
	for (int i=1;i<=Tot;++i)
	{
		memset(HAVE,0,sizeof(HAVE));
		for (int j=1;j<=K;++j)
			HAVE[CanUsed[i][j]]=1;
		HAVE['S']=HAVE['T']=1;
		memset(D,63,sizeof(D));
		memset(Vis,0,sizeof(Vis));
		Path[Sx][Sy]="";
		D[Sx][Sy]=0;
		Qx[1]=Sx;Qy[1]=Sy;

		int S=0,E=1,X,Y;
		while (S<E)
		{
			++S;
			X=Qx[S];Y=Qy[S];

			for (int f=0;f<4;++f)
				if (HAVE[Map[X+Fx[f]][Y+Fy[f]]] &&
						(D[X+Fx[f]][Y+Fy[f]]>D[X][Y]+1||
						(D[X+Fx[f]][Y+Fy[f]]==D[X][Y]+1&&Path[X+Fx[f]][Y+Fy[f]]>Path[X][Y]+Map[X+Fx[f]][Y+Fy[f]])))
				{
					D[X+Fx[f]][Y+Fy[f]]=D[X][Y]+1;
					Path[X+Fx[f]][Y+Fy[f]]=Path[X][Y]+Map[X+Fx[f]][Y+Fy[f]];
					if (!Vis[X+Fx[f]][Y+Fy[f]])
					{
						Vis[X+Fx[f]][Y+Fy[f]]=true;
						++E;
						Qx[E]=X+Fx[f];
						Qy[E]=Y+Fy[f];
					}
				}
		}
	//	cerr<<"X"<<endl;
	//	cerr<<FAns<<" "<<SAns<<endl;
	//	cerr<<D[Tx][Ty]<<" "<<Path[Tx][Ty]<<endl;
		if (FAns>D[Tx][Ty]||(FAns==D[Tx][Ty]&&SAns>Path[Tx][Ty]))
		{
			FAns=D[Tx][Ty];
			SAns=Path[Tx][Ty];
		}
	}
	for (int i=0;i<SAns.size()-1;++i)
		cout<<SAns[i];
	cout<<endl;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>

#define EPS 1e-9
#define INF 1070000000LL
#define MOD 1000000007LL
#define fir first
#define foreach(it,X) for(__typeof((X).begin()) it=(X).begin();it!=(X).end();it++)
#define ite iterator
#define mp make_pair
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define pb push_back
#define sec second
#define sz(x) ((int)x.size())

using namespace std;

struct timer{
	time_t start;
	timer(){start=clock();}
	~timer(){cerr<<1.*(clock()-start)/CLOCKS_PER_SEC<<" secs"<<endl;}
};

typedef istringstream iss;
typedef long long ll;
typedef pair<int,int> pi;
typedef stringstream sst;
typedef vector<int> vi;

int n,m,K;
char c[55][55];
int sy,sx,ty,tx;
map<int,string> d[55][55];
int dy[]={0,1,0,-1};
int dx[]={1,0,-1,0};

string shortest[55][55];
int smask[55][55];

struct state{
	int y,x;
	string s;
	int mask;
	state(int y,int x,string s,int mask):y(y),x(x),s(s),mask(mask){}
};

const bool operator < (const state& a, const state& b){
	return sz(a.s) > sz(b.s) || sz(a.s) == sz(b.s) && a.s > b.s;
}

const bool better(string s,string t){
	return sz(s) < sz(t) || sz(s) == sz(t) && s < t;
}

int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);

	cin>>n>>m>>K;
	rep2(i,1,n+1)rep2(j,1,m+1){
		cin>>c[i][j];
		if(c[i][j]=='S')sy=i,sx=j;
		if(c[i][j]=='T')ty=i,tx=j;
	}
	rep2(i,1,n+1)rep2(j,1,m+1){
		shortest[i][j]=string(n*m,'~');
	}
	d[sy][sx][0]="";
	priority_queue<state> Q;
	Q.push(state(sy,sx,"",0));
	while(sz(Q)){
		state s=Q.top();Q.pop();
		//cout<<s.y<<" "<<s.x<<" "<<s.s<<" "<<s.mask<<endl;
		if(s.y==ty && s.x==tx){
			cout<<s.s.substr(0,sz(s.s)-1);
			return 0;
		}
		rep(i,4){
			int ny=s.y+dy[i],nx=s.x+dx[i];
			if(!c[ny][nx] || c[ny][nx]=='S')continue;
			if(c[ny][nx]!='T' && __builtin_popcount(s.mask)==K && !(s.mask>>(c[ny][nx]-'a')&1))continue;

			string ndist=s.s + c[ny][nx];
			int nmask=s.mask|(c[ny][nx]=='T'?0:1<<(c[ny][nx]-'a'));

			if(!better(ndist,shortest[ny][nx]) && (smask[ny][nx]&nmask)==smask[ny][nx])continue;

			if(shortest[ny][nx][0]=='~'){
				shortest[ny][nx] = ndist;
				smask[ny][nx] = nmask;
			}

			if(d[ny][nx].find(nmask)==d[ny][nx].end() || better(ndist,d[ny][nx][nmask])){
				d[ny][nx][nmask] = ndist;
				Q.push(state(ny,nx,ndist,nmask));
			}
		}
	}
	cout<<-1;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>

#define EPS 1e-9
#define INF 1070000000LL
#define MOD 1000000007LL
#define fir first
#define foreach(it,X) for(__typeof((X).begin()) it=(X).begin();it!=(X).end();it++)
#define ite iterator
#define mp make_pair
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define pb push_back
#define sec second
#define sz(x) ((int)x.size())

using namespace std;

struct timer{
	time_t start;
	timer(){start=clock();}
	~timer(){cerr<<1.*(clock()-start)/CLOCKS_PER_SEC<<" secs"<<endl;}
};

typedef istringstream iss;
typedef long long ll;
typedef pair<int,int> pi;
typedef stringstream sst;
typedef vector<int> vi;

int n,m,K;
char c[55][55];
int sy,sx,ty,tx;
string d[55][55];
int dy[]={0,1,0,-1};
int dx[]={1,0,-1,0};

struct state{
	int y,x;
	string s;
	int mask;
	state(int y,int x,string s,int mask):y(y),x(x),s(s),mask(mask){}
};

const bool operator < (const state& a, const state& b){
	return sz(a.s) > sz(b.s) || sz(a.s) == sz(b.s) && a.s > b.s;
}

const bool better(string s,string t){
	return sz(s) < sz(t) || sz(s) == sz(t) && s < t;
}

int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);

	cin>>n>>m>>K;
	rep2(i,1,n+1)rep2(j,1,m+1){
		cin>>c[i][j];
		if(c[i][j]=='S')sy=i,sx=j;
		if(c[i][j]=='T')ty=i,tx=j;
	}
	rep2(i,1,n+1)rep2(j,1,m+1){
		d[i][j]=string(n*m,'~');
	}
	d[sy][sx]="";
	priority_queue<state> Q;
	Q.push(state(sy,sx,"",0));
	while(sz(Q)){
		state s=Q.top();Q.pop();
		//cout<<s.y<<" "<<s.x<<" "<<s.s<<" "<<s.mask<<endl;
		if(s.y==ty && s.x==tx){
			cout<<s.s.substr(0,sz(s.s)-1);
			return 0;
		}
		rep(i,4){
			int ny=s.y+dy[i],nx=s.x+dx[i];
			if(!c[ny][nx])continue;
			if(c[ny][nx]!='T' && __builtin_popcount(s.mask)==K && !(s.mask>>(c[ny][nx]-'a')&1))continue;
			if(better(s.s + c[ny][nx],d[ny][nx])){
				d[ny][nx] = s.s + c[ny][nx];
				Q.push(state(ny,nx,d[ny][nx],s.mask|(c[ny][nx]=='T'?0:1<<(c[ny][nx]-'a'))));
			}
		}
	}
	cout<<-1;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>

#define EPS 1e-9
#define INF 1070000000LL
#define MOD 1000000007LL
#define fir first
#define foreach(it,X) for(__typeof((X).begin()) it=(X).begin();it!=(X).end();it++)
#define ite iterator
#define mp make_pair
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define pb push_back
#define sec second
#define sz(x) ((int)x.size())

using namespace std;

struct timer{
	time_t start;
	timer(){start=clock();}
	~timer(){cerr<<1.*(clock()-start)/CLOCKS_PER_SEC<<" secs"<<endl;}
};

typedef istringstream iss;
typedef long long ll;
typedef pair<int,int> pi;
typedef stringstream sst;
typedef vector<int> vi;

int n,m,K;
char c[55][55];
int sy,sx,ty,tx;
map<int,string> d[55][55];
int dy[]={0,1,0,-1};
int dx[]={1,0,-1,0};

struct state{
	int y,x;
	string s;
	int mask;
	state(int y,int x,string s,int mask):y(y),x(x),s(s),mask(mask){}
};

const bool operator < (const state& a, const state& b){
	return sz(a.s) > sz(b.s) || sz(a.s) == sz(b.s) && a.s > b.s;
}

const bool better(string s,string t){
	return sz(s) < sz(t) || sz(s) == sz(t) && s < t;
}

int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);

	cin>>n>>m>>K;
	rep2(i,1,n+1)rep2(j,1,m+1){
		cin>>c[i][j];
		if(c[i][j]=='S')sy=i,sx=j;
		if(c[i][j]=='T')ty=i,tx=j;
	}
	d[sy][sx][0]="";
	priority_queue<state> Q;
	Q.push(state(sy,sx,"",0));
	while(sz(Q)){
		state s=Q.top();Q.pop();
		//cout<<s.y<<" "<<s.x<<" "<<s.s<<" "<<s.mask<<endl;
		if(s.y==ty && s.x==tx){
			cout<<s.s.substr(0,sz(s.s)-1);
			return 0;
		}
		rep(i,4){
			int ny=s.y+dy[i],nx=s.x+dx[i];
			if(!c[ny][nx] || c[ny][nx]=='S')continue;
			if(c[ny][nx]!='T' && __builtin_popcount(s.mask)==K && !(s.mask>>(c[ny][nx]-'a')&1))continue;
			int nmask=s.mask|(c[ny][nx]=='T'?0:1<<(c[ny][nx]-'a'));
			if(d[ny][nx].find(nmask)==d[ny][nx].end() || better(s.s + c[ny][nx],d[ny][nx][nmask])){
				d[ny][nx][nmask] = s.s + c[ny][nx];
				Q.push(state(ny,nx,d[ny][nx][nmask],nmask));
			}
		}
	}
	cout<<-1;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define ll long long
#define vc vector <char>
#define P 31
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  ll hsh;
  int len;
  place(ll _s=0,int _len=0)
  {
    hsh=_s;
    len=_len;
  }
};
ll fastPow(ll a,int b)
{
  ll f=1;
  while (b)
    if (b&1)b--,f=f*a;
    else b/=2,a*=a;
  return f;
}
map <ll,vc > st;
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool operator >(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]>b[i])return true;
  return false;
}
bool operator <(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]<b[i])return true;
  return false;
}
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].hsh=0;
  vc none;
  st[0]=none;
  d[x1][y1]=place(0,0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  int nx,ny;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      nx=v.f+X[i],ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        ll nhsh;
        vc path=st[d[v.f][v.s].hsh];
        if (a[nx][ny]!='T' && a[nx][ny]!='S')
        {
          nhsh=d[v.f][v.s].hsh+(a[nx][ny]-'a'+1)*fastPow(P,path.size());
          path.pb(a[nx][ny]);
          st[nhsh]=path;
        } else nhsh=d[v.f][v.s].hsh;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].hsh>path)//d[nx][ny].path>npath)
        {
          d[nx][ny]=place(nhsh,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && d[x2][y2].hsh<p)//p>d[x2][y2].path)
  {
    p=st[d[x2][y2].hsh];
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
  {
    for(int i=0;i<p.size();i++)cout<<p[i];
  }
  //#
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define x v.first
#define y v.second
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  int len,pr;
  place(int _pr=-1,int _len=INF)
  {
    pr=_pr;
    len=_len;
  }
};
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  place d[SZ][SZ];
  d[x2][y2].len=0;
  q.push(mp(x2,y2));
  int nx,ny;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny].len==INF)
      {
        d[nx][ny].len=d[x][y].len+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1].len==INF)return;
  q.push(mp(x1,y1));
  while (!q.empty())
  {
    int minc=255;
    v=q.front();
    q.pop();
    //cout<<x<<" "<<y<<endl;
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny].len<d[x][y].len)minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len)
      {
        q.push(mp(nx,ny));
        d[nx][ny].pr=c;
      }
    }
  }
  nx=x2-X[d[x2][y2].pr];
  ny=y2-Y[d[x2][y2].pr];
  while (d[nx][ny].pr!=-1)
  {
    path.pb(a[nx][ny]);
    x2=nx,y2=ny;
    nx=x2-X[d[x2][y2].pr];
    ny=y2-Y[d[x2][y2].pr];
  }
  reverse(path.begin(),path.end());
  if (d[x1][y1].len<mini || d[x1][y1].len==mini && path<p)
  {
    p=path;
    mini=d[x1][y1].len;
  }
  //cout<<"end!!!\n";
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define ll long long
#define vc vector <char>
#define P 31
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  ll hsh;
  int len;
  place(ll _s=0,int _len=0)
  {
    hsh=_s;
    len=_len;
  }
};
ll fastPow(ll a,int b)
{
  ll f=1;
  while (b)
    if (b&1)b--,f=f*a;
    else b/=2,a*=a;
  return f;
}
map <ll,vc > st;
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool operator >(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]>b[i])return true;
  return false;
}
bool operator <(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]<b[i])return true;
  return false;
}
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].hsh=0;
  vc none;
  st[0]=none;
  d[x1][y1]=place(0,0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  int nx,ny;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      nx=v.f+X[i],ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        ll nhsh;
        vc path=st[d[v.f][v.s].hsh];
        if (a[nx][ny]!='T' && a[nx][ny]!='S')
        {
          nhsh=d[v.f][v.s].hsh+(a[nx][ny]-'a'+1)*fastPow(P,path.size());
          path.pb(a[nx][ny]);
          st[nhsh]=path;
        } else nhsh=d[v.f][v.s].hsh;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].hsh>path)//d[nx][ny].path>npath)
        {
          d[nx][ny]=place(nhsh,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && d[x2][y2].hsh<p)//p>d[x2][y2].path)
  {
    p=st[d[x2][y2].hsh];
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
  {
    for(int i=0;i<p.size();i++)cout<<p[i];
  }
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define x v.first
#define y v.second
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  int len,pr;
  place(int _pr=-1,int _len=INF)
  {
    pr=_pr;
    len=_len;
  }
};
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  place d[SZ][SZ];
  bool u[SZ][SZ]={false};
  d[x2][y2].len=0;
  q.push(mp(x2,y2));
  int nx,ny;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny].len==INF)
      {
        d[nx][ny].len=d[x][y].len+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1].len==INF)return;
  q.push(mp(x1,y1));
  u[x1][y1]=true;
  while (!q.empty())
  {
    int minc=255;
    v=q.front();
    q.pop();
    //cout<<x<<" "<<y<<endl;
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny].len<d[x][y].len)minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len && !u[nx][ny])
      {
        q.push(mp(nx,ny));
        d[nx][ny].pr=c;
        u[nx][ny]=true;
      }
    }
  }
  nx=x2-X[d[x2][y2].pr];
  ny=y2-Y[d[x2][y2].pr];
  while (d[nx][ny].pr!=-1)
  {
    path.pb(a[nx][ny]);
    x2=nx,y2=ny;
    nx=x2-X[d[x2][y2].pr];
    ny=y2-Y[d[x2][y2].pr];
  }
  reverse(path.begin(),path.end());
  if (d[x1][y1].len<mini || d[x1][y1].len==mini && path<p)
  {
    p=path;
    mini=d[x1][y1].len;
  }
  //cout<<"end!!!\n";
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  string path;
  int len;
  place(string _s="",int _len=0)
  {
    path=_s;
    len=_len;
  }
};
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;;
string mn,p;
s_chr buk;
vector <char> b;
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].path="";
  d[x1][y1]=place("",0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      int nx=v.f+X[i];
      int ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        string npath;
        if (a[nx][ny]!='T' && a[nx][ny]!='S')npath=d[v.f][v.s].path+a[nx][ny];
        else npath=d[v.f][v.s].path;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].path>npath)
        {
          d[nx][ny]=place(npath,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && p>d[x2][y2].path)
  {
    p=d[x2][y2].path;
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (b.size()-ind<r)return;
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else cout<<p;
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define ppp pair<pair<int,int>,pair<int,int> >
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
void prisv(s_chr a,s_chr& b)
{
  b.clear();
  while (a.size()!=0)
  {
    b.insert((*a.begin()));
    a.erase(a.begin());
  }
}
class place
{
public:
  s_chr s;
  string path;
  int len;
  place(s_chr _s,string _path,int _len=0)
  {
    prisv(_s,s);
    path=_path;
    len=_len;
  }
};
vector <place> d[SZ][SZ][5];
char a[SZ][SZ];
queue <ppp> q;
int n,m,k;
bool chk(int x,int y,int t){return x>=0 && x<n && y>=0 && y<=m && t<=k;}
bool eq(s_chr a,s_chr b)
{
  while (a.size()!=0)
  {
    if ((*a.begin())!=(*b.begin()))return false;
    a.erase(a.begin());
    b.erase(b.begin());
  }
  return true;
}
int find(int x,int y,int t,const s_chr& a)
{
  for(int i=0;i<d[x][y][t].size();i++)
    if (eq(d[x][y][t][i].s,a))return i;
  return -1;
}
void new_set(s_chr a,s_chr& b,char c)
{
  prisv(a,b);
  if (c!='T' && c!='S') b.insert(c);
}
void bfs(int x1,int y1,int x2,int y2)
{
  s_chr c;
  d[x1][y1][0].pb(place(c,"",0));
  q.push(mp(mp(x1,y1),mp(0,0)));
  ppp v;
  int nx,ny;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      nx=v.f.f+X[i];
      ny=v.f.s+Y[i];
      place from=d[v.f.f][v.f.s][v.s.f][v.s.s];
      new_set(from.s,c,a[nx][ny]);
      int t=c.size();
      if (chk(nx,ny,t))
      {
        int ind=find(nx,ny,t,c);
        string npath;
        if (a[nx][ny]!='S' && a[nx][ny]!='T')npath=from.path+a[nx][ny];
        else npath=from.path;
        if (ind==-1)
        {
          d[nx][ny][t].pb(place(c,npath,from.len+1));
          q.push(mp(mp(nx,ny),mp(t,d[nx][ny][t].size()-1)));
        } else
        {
          if (d[nx][ny][t][ind].len>from.len+1 || d[nx][ny][t][ind].len==from.len+1 && d[nx][ny][t][ind].path>npath)
          {
            d[nx][ny][t][ind]=place(c,npath,from.len+1);
            q.push(mp(mp(nx,ny),mp(t,ind)));
          }
        }
      }
    }
  }
  int mini=INF;
  string p;
  for(int i=0;i<=k;i++)
    for(int j=0;j<d[x2][y2][i].size();j++)
      if (mini>d[x2][y2][i][j].len || mini==d[x2][y2][i][j].len && p>d[x2][y2][i][j].path)
      {
        mini=d[x2][y2][i][j].len;
        p=d[x2][y2][i][j].path;
      }
  if (mini==INF)cout<<-1;
  else cout<<p;
}
int main()
{
  int sx,sy,fx,fy;
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
    }
  bfs(sx,sy,fx,fy);
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
using namespace std;
#define x v.first
#define y v.second
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  int len,pr;
  place(int _pr=-1,int _len=INF)
  {
    pr=_pr;
    len=_len;
  }
};
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  place d[SZ][SZ];
  d[x2][y2].len=0;
  q.push(mp(x2,y2));
  int nx,ny;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny].len==INF)
      {
        d[nx][ny].len=d[x][y].len+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1].len==INF)return;
  q.push(mp(x1,y1));
  while (!q.empty())
  {
    int minc=255;
    v=q.front();
    q.pop();
    //cout<<x<<" "<<y<<endl;
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny].len<d[x][y].len)minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len)
      {
        q.push(mp(nx,ny));
        d[nx][ny].pr=c;
      }
    }
  }
  nx=x2-X[d[x2][y2].pr];
  ny=y2-Y[d[x2][y2].pr];
  while (d[nx][ny].pr!=-1)
  {
    path.pb(a[nx][ny]);
    x2=nx,y2=ny;
    nx=x2-X[d[x2][y2].pr];
    ny=y2-Y[d[x2][y2].pr];
  }
  reverse(path.begin(),path.end());
  if (d[x1][y1].len<mini || d[x1][y1].len==mini && path<p)
  {
    p=path;
    mini=d[x1][y1].len;
  }
  //cout<<"end!!!\n";
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
char a[SZ][SZ];
queue <pair<int,int> > q;
priority_queue < pair<pair<int,int>,pair<int,int> > > pq;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  int d[SZ][SZ],pr[SZ][SZ];
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j]=INF;
  bool u[SZ][SZ]={false};
  d[x2][y2]=0;
  q.push(mp(x2,y2));
  int nx,ny,x,y;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    x=v.first;
    y=v.second;
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny]==INF)
      {
        d[nx][ny]=d[x][y]+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1]==INF)return;
  pq.push(mp(mp(d[x1][y1],0),mp(x1,y1)));
  pr[x1][y1]=-1;
  u[x1][y1]=true;
  while (!pq.empty())
  {
    int minc=255;
    pair<pair<int,int>,pair<int,int> > v=pq.top();
    x=v.second.first;
    y=v.second.second;
    pq.pop();
    //cout<<x<<" "<<y<<endl;
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny]<d[x][y])minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && (a[nx][ny]==minc || a[nx][ny]=='T') && d[nx][ny]<d[x][y] && !u[nx][ny])
      {
        u[nx][ny]=true;
        pr[nx][ny]=c;
        pq.push(mp(mp(d[x][y]-1,-(int)a[nx][ny]),mp(nx,ny)));
      }
    }
  }
  nx=x2-X[pr[x2][y2]];
  ny=y2-Y[pr[x2][y2]];
  while (pr[nx][ny]!=-1)
  {
    path.pb(a[nx][ny]);
    x2=nx,y2=ny;
    nx=x2-X[pr[x2][y2]];
    ny=y2-Y[pr[x2][y2]];
  }
  reverse(path.begin(),path.end());
  if (d[x1][y1]<mini || d[x1][y1]==mini && path<p)
  {
    p=path;
    mini=d[x1][y1];
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define ll long long
#define vc vector <char>
#define P 31
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  ll hsh;
  int len;
  place(ll _s=0,int _len=0)
  {
    hsh=_s;
    len=_len;
  }
};
ll fastPow(ll a,int b)
{
  ll f=1;
  while (b)
    if (b&1)b--,f=f*a;
    else b/=2,a*=a;
  return f;
}
map <ll,vc > st;
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool operator >(ll a,vc& b)
{
  vc p=st[a];
  return p>b;
  //for(int i=0;i<p.size();i++)
    //if (p[i]>b[i])return true;
  //return false;
}
bool operator <(ll a,vc& b)
{
  vc p=st[a];
  //for(int i=0;i<p.size();i++)
    //if (p[i]<b[i])return true;
  //return false;
  return p<b;
}
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].hsh=0;
  vc none;
  st[0]=none;
  d[x1][y1]=place(0,0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  int nx,ny;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      nx=v.f+X[i],ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        ll nhsh;
        vc path=st[d[v.f][v.s].hsh];
        if (a[nx][ny]!='T' && a[nx][ny]!='S')
        {
          nhsh=d[v.f][v.s].hsh+(a[nx][ny]-'a'+1)*fastPow(P,path.size());
          path.pb(a[nx][ny]);
          st[nhsh]=path;
        } else nhsh=d[v.f][v.s].hsh;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].hsh>path)//d[nx][ny].path>npath)
        {
          d[nx][ny]=place(nhsh,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  //if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && d[x2][y2].hsh<p)//p>d[x2][y2].path)
  {
    p=st[d[x2][y2].hsh];
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
  {
    for(int i=0;i<p.size();i++)cout<<p[i];
  }
  //#
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define x v.first
#define y v.second
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  int len,pr;
  place(int _pr=-1,int _len=INF)
  {
    pr=_pr;
    len=_len;
  }
};
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  place d[SZ][SZ];
  bool u[SZ][SZ]={false};
  d[x2][y2].len=0;
  q.push(mp(x2,y2));
  int nx,ny;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny].len==INF)
      {
        d[nx][ny].len=d[x][y].len+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1].len==INF)return;
  q.push(mp(x1,y1));
  u[x1][y1]=true;
  while (!q.empty())
  {
    int minc=255;
    v=q.front();
    q.pop();
    //cout<<x<<" "<<y<<endl;
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny].len<d[x][y].len)minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len && !u[nx][ny])
      {
        q.push(mp(nx,ny));
        d[nx][ny].pr=c;
        u[nx][ny]=true;
      } else if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len && a[nx-X[d[nx][ny].pr]][ny-Y[d[nx][ny].pr]]>a[x][y])d[nx][ny].pr=c;
    }
  }
  nx=x2-X[d[x2][y2].pr];
  ny=y2-Y[d[x2][y2].pr];
  while (d[nx][ny].pr!=-1)
  {
    path.pb(a[nx][ny]);
    x2=nx,y2=ny;
    nx=x2-X[d[x2][y2].pr];
    ny=y2-Y[d[x2][y2].pr];
  }
  reverse(path.begin(),path.end());
  if (d[x1][y1].len<mini || d[x1][y1].len==mini && path<p)
  {
    p=path;
    mini=d[x1][y1].len;
  }
  //cout<<"end!!!\n";
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  string path;
  int len;
  place(string _s="",int _len=0)
  {
    path=_s;
    len=_len;
  }
};
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;;
string mn,p;
s_chr buk;
vector <char> b;
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].path="";
  d[x1][y1]=place("",0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      int nx=v.f+X[i];
      int ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        string npath;
        if (a[nx][ny]!='T' && a[nx][ny]!='S')npath=d[v.f][v.s].path+a[nx][ny];
        else npath=d[v.f][v.s].path;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].path>npath)
        {
          d[nx][ny]=place(npath,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && p>d[x2][y2].path)
  {
    p=d[x2][y2].path;
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else cout<<p;
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1},K='z'-'a'+2;
char a[SZ][SZ];
queue <pair<int,int> > q;
//priority_queue < pair<pair<int,int>,pair<int,int> > > pq;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  vc path;
  path.clear();
  int d[SZ][SZ],pr[SZ][SZ];
  bool u[SZ][SZ]={false};
  vector<vector<pair<int,int> > > qe[K];
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j]=INF;
  d[x2][y2]=0;
  q.push(mp(x2,y2));
  int nx,ny,x,y;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    x=v.first;
    y=v.second;
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny]==INF)
      {
        d[nx][ny]=d[x][y]+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1]==INF)return;
  //��� �� ������!!
  pr[x1][y1]=-1;
  u[x1][y1]=true;
  for(int i=0;i<K;i++)qe[i].resize(d[x1][y1]);
  qe[K-1][d[x1][y1]-1].pb(mp(x1,y1));
  int minc=K-1,fminc,newminc;
  for(int i=d[x1][y1]-1;i>=0;i--)
  {
    newminc=K;
    //cout<<minc<<endl;
    //cout<<qe[minc][i].size()<<endl;
    for(int j=0;j<qe[minc][i].size();j++)
    {
      fminc=K-1;
      x=qe[minc][i][j].first;
      y=qe[minc][i][j].second;
      for(int c=0;c<4;c++)
      {
        nx=x+X[c];
        ny=y+Y[c];
        if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny]<d[x][y])fminc=min(fminc,(int)a[nx][ny]-'a');
      }
      for(int c=0;c<4;c++)
      {
        nx=x+X[c];
        ny=y+Y[c];
        if (a[nx][ny]=='T')
        {
          pr[x2][y2]=c;
          nx=x2-X[pr[x2][y2]];
          ny=y2-Y[pr[x2][y2]];
          while (pr[nx][ny]!=-1)
          {
            path.pb(a[nx][ny]);
            x2=nx,y2=ny;
            nx=x2-X[pr[x2][y2]];
            ny=y2-Y[pr[x2][y2]];
          }
          reverse(path.begin(),path.end());
          if (d[x1][y1]<mini || d[x1][y1]==mini && path<p)
          {
            p=path;
            mini=d[x1][y1];
          }
          return;
        }
        /////
        if (chk(nx,ny) && a[nx][ny]-'a'==fminc && d[nx][ny]<d[x][y] && !u[nx][ny])
        {
          u[nx][ny]=true;
          pr[nx][ny]=c;
          qe[fminc][i-1].pb(mp(nx,ny));
        }
      }
      newminc=min(newminc,fminc);
    }
    minc=newminc;
  }
}
//��������� ���������
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define INF 1<<30
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define ll long long
#define vc vector <char>
#define P 31
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  ll hsh;
  int len;
  place(ll _s=0,int _len=0)
  {
    hsh=_s;
    len=_len;
  }
};
ll fastPow(ll a,int b)
{
  ll f=1;
  while (b)
    if (b&1)b--,f=f*a;
    else b/=2,a*=a;
  return f;
}
map <ll,vc > st;
place d[SZ][SZ];
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool operator >(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]>b[i])return true;
  return false;
}
bool operator <(ll a,vc& b)
{
  vc p=st[a];
  for(int i=0;i<p.size();i++)
    if (p[i]<b[i])return true;
  return false;
}
bool chk(int x,int y){return x>=0 && x<n && y>=0 && y<m && (a[x][y]=='T' || mn.find(a[x][y])!=-1);}
void bfs(int x1,int y1,int x2,int y2)
{
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)d[i][j].len=INF,d[i][j].hsh=0;
  vc none;
  st[0]=none;
  d[x1][y1]=place(0,0);
  q.push(mp(x1,y1));
  pair <int,int> v;
  int nx,ny;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int i=0;i<4;i++)
    {
      nx=v.f+X[i],ny=v.s+Y[i];
      if (chk(nx,ny))
      {
        ll nhsh;
        vc path=st[d[v.f][v.s].hsh];
        if (a[nx][ny]!='T' && a[nx][ny]!='S')
        {
          nhsh=d[v.f][v.s].hsh+(a[nx][ny]-'a'+1)*fastPow(P,path.size());
          path.pb(a[nx][ny]);
          st[nhsh]=path;
        } else nhsh=d[v.f][v.s].hsh;
        if (d[nx][ny].len>d[v.f][v.s].len+1 || d[nx][ny].len==d[v.f][v.s].len+1 && d[nx][ny].hsh>path)//d[nx][ny].path>npath)
        {
          d[nx][ny]=place(nhsh,d[v.f][v.s].len+1);
          q.push(mp(nx,ny));
        }
      }
    }
  }
  if (d[x2][y2].len==INF)return;
  if (mini>d[x2][y2].len || d[x2][y2].len==mini && d[x2][y2].hsh<p)//p>d[x2][y2].path)
  {
    p=st[d[x2][y2].hsh];
    mini=d[x2][y2].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
  {
    for(int i=0;i<p.size();i++)cout<<p[i];
  }
  //
  return 0;
}


#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
#define x v.first
#define y v.second
#define mp make_pair
#define pb push_back
#define INF (1<<30)
#define sqr(x) ((x)*(x))
#define s_chr set <char>
#define SZ 52
#define vc vector<char>
const int X[]={-1,0,1,0},Y[]={0,1,0,-1};
class place
{
public:
  int len;
  vc path;
  place(int _len=INF)
  {
    len=_len;
  }
};
char a[SZ][SZ];
queue <pair<int,int> > q;
int n,m,k,mini=INF,sx,sy,fx,fy;
string mn;
vc p;
s_chr buk;
vc b;
bool chk(int i,int j){return (i>=0 && i<n && j>=0 && j<m && (a[i][j]=='S' || a[i][j]=='T' || (int)mn.find(a[i][j])!=-1));}
void bfs(int x1,int y1,int x2,int y2)
{
  place d[SZ][SZ];
  bool u[SZ][SZ]={false};
  d[x2][y2].len=0;
  q.push(mp(x2,y2));
  int nx,ny;
  pair<int,int> v;
  while (!q.empty())
  {
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && d[nx][ny].len==INF)
      {
        d[nx][ny].len=d[x][y].len+1;
        q.push(mp(nx,ny));
      }
    }
  }
  if (d[x1][y1].len==INF)return;
  q.push(mp(x1,y1));
  u[x1][y1]=true;
  while (!q.empty())
  {
    int minc=255;
    v=q.front();
    q.pop();
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      if (chk(nx,ny) && a[nx][ny]!='T' && d[nx][ny].len<d[x][y].len)minc=min(minc,(int)a[nx][ny]);
    }
    for(int c=0;c<4;c++)
    {
      nx=x+X[c];
      ny=y+Y[c];
      vc npath;
      if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len && !u[nx][ny])
      {
        q.push(mp(nx,ny));
        npath=d[x][y].path;
        if (a[nx][ny]!='T') npath.pb(a[nx][ny]);
        d[nx][ny].path=npath;
        u[nx][ny]=true;
      } else
      {
        npath=d[x][y].path;
        if (a[nx][ny]!='T') npath.pb(a[nx][ny]);
        if (chk(nx,ny) && (minc==a[nx][ny] || a[nx][ny]=='T') && d[nx][ny].len<d[x][y].len && npath<d[nx][ny].path)d[nx][ny].path=npath;
      }
    }
  }
  if (d[x1][y1].len<mini || d[x1][y1].len==mini && d[x2][y2].path<p)
  {
    p=d[x2][y2].path;
    mini=d[x1][y1].len;
  }
}
void gen(int r,int ind)
{
  if (r==0)
  {
    bfs(sx,sy,fx,fy);
    return;
  } else if (ind>=(int)b.size())return;
  else {
    mn=mn+b[ind];
    gen(r-1,ind+1);
    mn.erase(mn.size()-1,1);
    gen(r,ind+1);
  }
}
int main()
{
  cin>>n>>m>>k;
  for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if (a[i][j]=='S')sx=i,sy=j;
      else if (a[i][j]=='T')fx=i,fy=j;
      else buk.insert(a[i][j]);
    }
  while (buk.size())
  {
    b.pb((*buk.begin()));
    buk.erase(buk.begin());
  }
  gen(min(k,(int)b.size()),0);
  if (mini==INF)cout<<-1;
  else
    for(int i=0;i<(int)p.size();i++)cout<<p[i];
  return 0;
}


/*
 * C. Track.cpp
 *
 *  Created on: 2011-5-16
 *      Author: user
 */

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <climits>
#include <cstring>
#define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e)
using namespace std;

const int N_ALPHA = 27;
const int MAX_N = 50 + 1;
bool can[N_ALPHA];
int n, m, k;
int map[MAX_N * MAX_N];
string ans;
bool hasAns;
int dist[MAX_N * MAX_N];
int lab[MAX_N * MAX_N];
int prev[MAX_N * MAX_N];
int que[MAX_N * MAX_N], qh, qt;

int VS, VT;

bool cmp(int a, int b) {
	if (lab[a] != lab[b])
		return lab[a] < lab[b];
	return map[a] < map[b];
}

bool equal(int a, int b) {
	return lab[a] == lab[b] && map[a] == map[b];
}

void doit() {
	qh = qt = 0;
	que[qt++] = VS;
	memset(dist, -1, sizeof dist);
	dist[VS] = 0;
	lab[VS] = 0;
	prev[VS] = -1;
	while (qh < qt) {
		int nLab = 0;
		static int tmp[MAX_N * MAX_N];
		sort(que + qh, que + qt, cmp);
		for (int i = qh; i < qt; ++i) {
			if (i != qh && equal(que[i - 1], que[i]))
				tmp[i] = nLab - 1;
			else
				tmp[i] = nLab++;
		}
		int nQt = qt;
		for (int i = qh; i < qt; ++i) {
			int me = que[i];
			lab[me] = tmp[i];
			int r = me / m, c = me % m;
			for (int dr = -1; dr <= 1; dr++)
				for (int dc = -1; dc <= 1; dc++)
					if (dr ^ dc) {
						int nr = r + dr, nc = c + dc;
						if (nr < 0 || nr >= n || nc < 0 || nc >= m)
							continue;
						int v = nr * m + nc;
						if (!can[map[v]] || dist[v] != -1)
							continue;
						prev[v] = me;
						lab[v] = lab[me];
						dist[v] = dist[me] + 1;
						que[nQt++] = v;
					}
		}
		qh = qt;
		qt = nQt;
	}

	if (dist[VT] == -1)
		return;

	int len = dist[VT] - 1;
	if (hasAns && len > ans.size())
		return;

	string cur = "";
	int at = prev[VT];
	while (at != VS) {
		cur += 'a' + map[at];
		at = prev[at];
	}
	reverse(cur.begin(), cur.end());
	if (!hasAns) {
		hasAns = true;
		ans = cur;
	} else if (cur < ans) {
		ans = cur;
	}
}

void dfs(int cur, int rest) {
	if (cur == N_ALPHA) {
		if (rest == 0)
			doit();
		return;
	}
	if (rest > 0) {
		can[cur] = true;
		dfs(cur + 1, rest - 1);
		can[cur] = false;
	}
	dfs(cur + 1, rest);
}

int main() {
	hasAns = false;
	cin >> n >> m >> k;
	for (int r = 0; r < n; ++r) {
		for (int c = 0; c < m; ++c) {
			char ch;
			while (ch = getchar(), ch == '\n')
				;
			map[r * m + c] = ch - 'a';
		}
	}
	VS = 0;
	VT = n * m - 1;
	map[VS] = map[VT] = N_ALPHA;
	memset(can, false, sizeof can);
	can[N_ALPHA] = true;
	dfs(0, k);

	if (!hasAns)
		puts("-1");
	else
		cout << ans << endl;
}


/*
 * C. Track.cpp
 *
 *  Created on: 2011-5-16
 *      Author: user
 */

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <climits>
#include <cstring>
#define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e)
using namespace std;

const int N_ALPHA = 27;
const int MAX_N = 50 + 1;
bool can[N_ALPHA];
int n, m, k;
int map[MAX_N * MAX_N];
string ans;
bool hasAns;
int dist[MAX_N * MAX_N];
int lab[MAX_N * MAX_N];
int prev[MAX_N * MAX_N];
int que[MAX_N * MAX_N], qh, qt;

int VS, VT;

bool cmp(int a, int b) {
	if (lab[a] != lab[b])
		return lab[a] < lab[b];
	return map[a] < map[b];
}

bool equal(int a, int b) {
	return lab[a] == lab[b] && map[a] == map[b];
}

void doit() {
	qh = qt = 0;
	que[qt++] = VS;
	memset(dist, -1, sizeof dist);
	dist[VS] = 0;
	lab[VS] = 0;
	prev[VS] = -1;
	while (qh < qt) {
		int nLab = 0;
		static int tmp[MAX_N * MAX_N];
		sort(que + qh, que + qt, cmp);
		for (int i = qh; i < qt; ++i) {
			if (i != qh && equal(que[i - 1], que[i]))
				tmp[i] = nLab - 1;
			else
				tmp[i] = nLab++;
		}
		int nQt = qt;
		for (int i = qh; i < qt; ++i) {
			int me = que[i];
			lab[me] = tmp[i];
			int r = me / m, c = me % m;
			for (int dr = -1; dr <= 1; dr++)
				for (int dc = -1; dc <= 1; dc++)
					if (dr == 0 ^ dc == 0) {
						int nr = r + dr, nc = c + dc;
						if (nr < 0 || nr >= n || nc < 0 || nc >= m)
							continue;
						int v = nr * m + nc;
						if (!can[map[v]] || dist[v] != -1)
							continue;
						prev[v] = me;
						lab[v] = lab[me];
						dist[v] = dist[me] + 1;
						que[nQt++] = v;
					}
		}
		qh = qt;
		qt = nQt;
	}

	if (dist[VT] == -1)
		return;

	int len = dist[VT] - 1;
	if (hasAns && len > ans.size())
		return;
	string cur = "";
	int at = prev[VT];
	while (at != VS) {
		cur += 'a' + map[at];
		at = prev[at];
	}
	reverse(cur.begin(), cur.end());
	if (!hasAns) {
		hasAns = true;
		ans = cur;
	} else if (len < ans.size() || cur < ans) {
		ans = cur;
	}
}

void dfs(int cur, int rest) {
	if (cur == N_ALPHA) {
		if (rest == 0)
			doit();
		return;
	}
	if (rest > 0) {
		can[cur] = true;
		dfs(cur + 1, rest - 1);
		can[cur] = false;
	}
	dfs(cur + 1, rest);
}

int main() {
	hasAns = false;
	cin >> n >> m >> k;
	for (int r = 0; r < n; ++r) {
		for (int c = 0; c < m; ++c) {
			char ch;
			while (ch = getchar(), ch == '\n')
				;
			int me = r * m + c;
			map[me] = ch - 'a';
			if (ch == 'S')
				map[VS = me] = N_ALPHA;
			if (ch == 'T')
				map[VT = me] = N_ALPHA;
		}
	}
	memset(can, false, sizeof can);
	can[N_ALPHA] = true;
	dfs(0, k);

	if (!hasAns)
		puts("-1");
	else
		cout << ans << endl;
}