#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define SZ(x) ((int)x.size())
#define lowbit(x) x&-x
#define pb push_back
#define ALL(x) (x).begin(),(x).end()
#define UNI(x) sort(ALL(x)),x.resize(unique(ALL(x))-x.begin())
#define GETPOS(c,x) (lower_bound(ALL(c),x)-c.begin())
#define LEN(x) strlen(x)
#define MS0(x) memset((x),0,sizeof((x)))
#define Rint register int
#define ls (u<<1)
#define rs (u<<1|1)
typedef unsigned int unit;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> Vi;
typedef vector<ll> Vll;
typedef vector<pii> Vpii;
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(ull &x) { scanf("%llu", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
template<class T> void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const ll &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template<class T,class U> void _W(const pair<T,U> &x) {_W(x.fi);putchar(' '); _W(x.se);}
template<class T> void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W(const T &head, const U &... tail) { _W(head); putchar(sizeof...(tail) ? ' ' : '\n'); W(tail...); }
const int MOD=1e9+7,mod=998244353;
ll qpow(ll a,ll b) {ll res=1;a%=MOD; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
const int MAXN=4e5+10,MAXM=1e7+10;
const int INF=INT_MAX,SINF=0x3f3f3f3f;
const ll llINF=LLONG_MAX;
const int inv2=(MOD+1)/2;
const int Lim=1<<20;

int n,k;
char s[MAXN];
int nxt[MAXN][20],sum[MAXN][20];
int mx[30];
Vll vec[MAXN];

bool chk(int m)
{
    for(int j=0;j<k;j++)nxt[n+1][j]=nxt[n+2][j]=n+2;
    for(int i=n;i;i--)
        for(int j=0;j<k;j++)
        {
            if(sum[i+m-1][j]-sum[i-1][j]==m)
            nxt[i][j]=i+m;
            else nxt[i][j]=nxt[i+1][j];
        }
    Vi dp((1<<k),n+2);
    dp[0]=1;
    for(int s=0;s<(1<<k);s++)
        for(int i=0;i<k;i++)if(!(s&(1<<i)))
        {
            dp[s|(1<<i)]=min(dp[s|(1<<i)],nxt[dp[s]][i]);
        }
    return dp.back()<=n+1;
}

void solve()
{
    R(n,k);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<k;j++)
        {
            sum[i][j]=sum[i-1][j]+(s[i]=='a'+j)+(s[i]=='?');
        }
    }
    int l=1,r=n,res=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(chk(mid))l=mid+1,res=mid;
        else r=mid-1;
    }
    W(res);
}

int main()
{
    int T=1;
    //scanf("%d",&T);
    for(int kase=1;kase<=T;kase++)
    {
        //printf("Case #%d: ",kase);
        solve();
    }
    return 0;
}
