#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdlib>
#define N 500010
#define sup 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define ll long long
using namespace std;

int n,k;
string s; 
inline int read(){
	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();
	}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();
	}return x*f;
}
bool check(int d){
	vector<int> lst(k, n);
	vector<vector<int>> pos(n + 1, vector<int>(k, n + 1));
	for (int i = n - 1; i >= 0; --i){
		if (s[i] != '?'){
			lst[s[i] - 'a'] = i;
		}
		int cur = n;          //特殊的转移，找能放k个j的位置，正向一遍反向一遍 
		for(int j=0;j<k;j++){
			pos[i][j] = (i + d <= cur ? i + d : pos[i + 1][j]);
			cur = min(cur, lst[j]);
		}
		cur = n;
		for (int j = k - 1; j >= 0; --j){
			if (i + d > cur) pos[i][j] = pos[i + 1][j];
			cur = min(cur, lst[j]);
		}
	}
	vector<int> dp(1 << k, n + 1);
	dp[0] = 0;
	for(int mask=0;mask<(1<<k);mask++) if (dp[mask] < n + 1){
		for(int i=0;i<k;i++)if (!((mask >> i) & 1))
			dp[mask | (1 << i)] = min(dp[mask | (1 << i)], pos[dp[mask]][i]);
	}
	return dp[(1 << k) - 1] <= n;
}

int main() {
	n=read(),k=read();
	cin>>s;
	int l = 0, r = n;
	while (l < r){
		int m = (l + r+1)>>1;
		if (check(m)){
			l = m ;
		}
		else{
			r = m-1;
		}
	}
	printf("%d\n",l);
	return 0;
}