#pragma region
#include <bits/stdc++.h>
using namespace std;
// Common Type shorteners and int128
using ll = long long; using ull = unsigned long long; using ld = long double;
using pii = pair<int, int>; using pll = pair<ll, ll>;
template <typename T> using vec = vector<T>;
template <typename K, typename V> using umap = unordered_map<K, V>; template <typename K> using uset = unordered_set<K>;
using vi = vec<int>; using vl = vec<ll>; using vpi = vec<pii>; using vpl = vec<pll>;
#ifdef __SIZEOF_INT128__
using int128 = __int128_t; using uint128 = __uint128_t;
#endif
template<typename I> string intStr(I x) { string ret; while (x > 0) { ret += (x % 10) + '0'; x /= 10; } reverse(ret.begin(), ret.end()); return ret; } // Int to string
// Shorthand Macros
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define mpr make_pair
#define pb push_back
#define popcount __builtin_popcount
#define clz __builtin_clz
#define ctz __builtin_ctz
// Shorthand Function Macros
#define sz(x) ((int)((x).size()))
#define all(x) (x).begin(), (x).end()
#define rep(i, a, b) for (__typeof(a) i = a; i < b; i++)
#define reprev(i, a, b) for (__typeof(a) i = a; i > b; i--)
#define repi(a, b) rep(i, a, b)
#define repj(a, b) rep(j, a, b)
#define repk(a, b) rep(k, a, b)
#define Cmplt(type) bool operator<(const type &o) const
#define Cmpgt(type) bool operator>(const type &o) const
#define Cmpfn(name, type) bool name(const type &a, const type &b)
#define Inop(type) istream& operator>>(istream& in, type &o)
#define Outop(type) ostream& operator<<(ostream& out, type o)
#define Pow2(x) (1LL << (x))
#define scn(type, ...) type __VA_ARGS__; scan(__VA_ARGS__) // scn -> Short for SCan New
// Shorthand Functions
template<typename T> inline void maxa(T& st, T v) { st = max(st, v); }
template<typename T> inline void mina(T& st, T v) { st = min(st, v); }
inline void setprec(ostream& out, int prec) { out << setprecision(prec) << fixed; }
// Out operators and printing for arrays and vectors
template <typename T> ostream& operator<<(ostream& out,vector<T> iter){out<<"[";for(auto t:iter){out<<t<<", ";}out<<"]";return out;}
template <typename T> string arrayStr(T *arr,int sz){string ret = "[";for(int i=0;i<sz;i++){ret+=to_string(arr[i])+", "; } return ret + "]";}
template <typename T> void printArray(T *arr,int sz){for(int i=0;i<sz;i++){cout<<arr[i]<<" "; } cout<<"\n";}
// I/O Operations
inline void scan(){}
template<typename F, typename... R> inline void scan(F &f,R&... r){cin>>f;scan(r...);}
template <typename F> inline void println(F t){cout<<t<<'\n';}
template<typename F, typename... R> inline void println(F f,R... r){cout<<f<<" ";println(r...);}
inline void print(){}
template<typename F, typename... R> inline void print(F f,R... r){cout<<f;print(r...);}
// Debugging
#define db(x) cout << (#x) << ": " << x << ", "
#define dblb(s) cout << "[" << s << "] "
#define dbbin(x, n) cout << (#x) << ": " << bitset<n>(x) << ", "
#define dbarr(x, n) cout << (#x) << ": " << arrayStr((x), (n)) << ", "
#define dbln cout << endl;
#pragma endregion

const ld EPS = 1e-9;
const int MN = 1e6 + 1;
int n, k, len;
string s;
bool up[MN];

// dp
using pdi = pair<ld, int>; // best, number of use

ll pfx[MN];
pdi dp[MN];

ll rsq(int l, int r) {
    return pfx[r] - pfx[l - 1];
}

pdi runDP(ld C) {
    // db(C); db(pfx[n]); dbln;

    deque<int> Q; Q.pb(0);
    dp[0] = {0, 0};
    repi(1, n + 1) {
        while (!Q.empty() && Q.front() < i - len)
            Q.pop_front();

        pdi best = dp[i - 1];
        best.first += up[i];
        ld alt = dp[Q.front()].first + C;
        if (alt < best.first) {
            best.first = alt;
            best.second = dp[Q.front()].second + 1;
        }

        dp[i] = best;

        while (!Q.empty() && dp[Q.back()].first > best.first)
            Q.pop_back();
        Q.pb(i);

        // db(i); db(best.first); db(best.second); dbln;
    }

    return dp[n];
}

int solve() {
    repi(1, n + 1)
        pfx[i] = pfx[i - 1] + up[i];

    double l = 0, r = n;
    while (l + EPS < r) {
        double mid = (l + r) / 2.;
        auto tans = runDP(mid);

        if (tans.second <= k)
            r = mid;
        else
            l = mid;
    }

    auto ans = runDP(r);
    // assert(ans.second == k);
    // db(r); dbln;
    return (int)(round(ans.first - k * r));
}

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

    scan(n, k, len, s);

    repi(1, n + 1)
        up[i] = isupper(s[i - 1]) != 0;

    // do and flip
    int best = solve();
    repi(1, n + 1)
        up[i] ^= 1;
    // dblb("tolow"); db(best); dbln;
    // dblb("-------------------------"); dbln;
    mina(best, solve());
    println(best);

    return 0;
}


#include <cctype>
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

#define SZ(a) ((int)a.size())
#define EPS (1e-9)

typedef vector<char> vc;
typedef vector<int> vi;

typedef long long LAMBDA;
typedef pair<LAMBDA, int> DP;

DP solve(int l, const vi &s, const LAMBDA lambda) {
    const int n = SZ(s);

    vector<DP> dp(n);

    for (int i = 0; i < n; i++)
    {
        DP not_convert = i >= 1 ? dp[i - 1] : DP(0, 0);
        not_convert.first += s[i];

        DP convert = i >= l ? dp[i - l] : DP(0, 0);
        convert.first += lambda;
        ++convert.second;

        dp[i] = min(convert, not_convert);
    }

    return dp[n - 1];
}

int solve(int k, int l, const vi &s) {
    LAMBDA left = 0, right = s.size();

    while(
        (right - left) > EPS
        &&
        (is_same<LAMBDA, long double>::value || left < right - 1)
    ) {
        LAMBDA lambda = (left + right) / 2;

        if (solve(l, s, lambda).second <= k) {
            right = lambda;
        } else {
            left = lambda;
        }
    }

    const auto vc = solve(l, s, right);
    int answer = vc.first - right * k;

    return answer;
}

int solve(int k, int l, const string &s) {
    const int n = SZ(s);

    vi is_upper(n);

    transform(s.begin(), s.end(), is_upper.begin(), [&](const char &c) { return 0 != isupper(c); });

    vi is_lower(n);

    transform(s.begin(), s.end(), is_lower.begin(), [&](const char &c) { return 0 != islower(c); });

    int min_upper = solve(k, l, is_upper);
    int min_lower = solve(k, l, is_lower);

    return min(min_upper, min_lower);
}

int main(){

#ifdef DEBUG
    cout << "DEBUG" << endl;
    cerr << "DEBUG" << endl;
    assert(2 == solve(2, 2, vi({0,1,0,1,0,0,1,1,0,0,0,0,1,1,0})));
    assert(2 == solve(2, 2, "AaAaAAaaAAAAaaA"));
    assert(1 == solve(2, 2, vi({1,0,1,0,0,0,1,1,0})));
    assert(1 == solve(2, 2, "aAaAAAaaA"));
    assert(0 == solve(1, 4, "PikMike"));
    assert(0 == solve(2, 6, "aBcdEFGHIJklMn"));
#endif
    int n, k, l;
    string s;

    while(cin >> n >> k >> l >> s) {
        cout << solve(k, l, s) << endl;
    }

    return 0;
}


#include <cctype>
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

#define SZ(a) ((int)a.size())
#define EPS (1e-9)

typedef vector<char> vc;
typedef vector<int> vi;

typedef long long LAMBDA;
typedef pair<LAMBDA, int> DP;

DP solve(int l, const vi &s, const LAMBDA lambda) {
    const int n = SZ(s);

    vector<DP> dp(n);

    for (int i = 0; i < n; i++)
    {
        DP not_convert = i >= 1 ? dp[i - 1] : DP(0, 0);
        not_convert.first += s[i];

        DP convert = i >= l ? dp[i - l] : DP(0, 0);
        convert.first += lambda;
        ++convert.second;

        dp[i] = min(convert, not_convert);
    }

    return dp[n - 1];
}

int solve(int k, int l, const vi &s) {
    LAMBDA left = 0, right = s.size();

    auto vc = solve(l, s, 0.0);
    int answer;

    if (vc.second <= k) {
        answer = vc.first;
    } else {
        while(
            (right - left) > EPS
            &&
            (is_same<LAMBDA, long double>::value || left < right - 1)
        ) {
            LAMBDA lambda = (left + right) / 2;

            if (solve(l, s, lambda).second <= k) {
                right = lambda;
            } else {
                left = lambda;
            }
        }

        vc = solve(l, s, right);
        answer = vc.first - right * k;
    }

    return answer;
}

int solve(int k, int l, const string &s) {
    const int n = SZ(s);

    vi is_upper(n);

    transform(s.begin(), s.end(), is_upper.begin(), [&](const char &c) { return 0 != isupper(c); });

    vi is_lower(n);

    transform(s.begin(), s.end(), is_lower.begin(), [&](const char &c) { return 0 != islower(c); });

    int min_upper = solve(k, l, is_upper);
    int min_lower = solve(k, l, is_lower);

    return min(min_upper, min_lower);
}

int main(){

#ifdef DEBUG
    cout << "DEBUG" << endl;
    cerr << "DEBUG" << endl;
    assert(0 == solve(10, 7, "eTnmeHRmaTetSTsGqigLFYciMFLbwJHCScPRRIvxCFcevZVRmprk"));
    assert(2 == solve(2, 2, vi({0,1,0,1,0,0,1,1,0,0,0,0,1,1,0})));
    assert(2 == solve(2, 2, "AaAaAAaaAAAAaaA"));
    assert(1 == solve(2, 2, vi({1,0,1,0,0,0,1,1,0})));
    assert(1 == solve(2, 2, "aAaAAAaaA"));
    assert(0 == solve(1, 4, "PikMike"));
    assert(0 == solve(2, 6, "aBcdEFGHIJklMn"));
#endif
    int n, k, l;
    string s;

    while(cin >> n >> k >> l >> s) {
        cout << solve(k, l, s) << endl;
    }

    return 0;
}


#include <cctype>
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

#define SZ(a) ((int)a.size())
#define EPS (1e-9)

typedef vector<char> vc;
typedef vector<int> vi;

typedef long long LAMBDA;
typedef pair<LAMBDA, int> DP;

DP solve(int l, const vi &s, const LAMBDA lambda) {
    const int n = SZ(s);

    vector<DP> dp(n);

    for (int i = 0; i < n; i++)
    {
        DP not_convert = i >= 1 ? dp[i - 1] : DP(0, 0);
        not_convert.first += s[i];

        DP convert = i >= l ? dp[i - l] : DP(0, 0);
        convert.first += lambda;
        ++convert.second;

        dp[i] = min(convert, not_convert);
    }

    return dp[n - 1];
}

int solve(int k, int l, const vi &s) {
    LAMBDA left = 0, right = 1e18;

    while(
        (right - left) > EPS
        &&
        (is_same<LAMBDA, long double>::value || left < right - 1)
    ) {
        LAMBDA lambda = (left + right) / 2.0;

        if (solve(l, s, lambda).second <= k) {
            right = lambda;
        } else {
            left = lambda;
        }
    }

    const auto vc = solve(l, s, right);
    int answer = vc.first - right * k;

    return answer;
}

int solve(int k, int l, const string &s) {
    const int n = SZ(s);

    vi is_upper(n);

    transform(s.begin(), s.end(), is_upper.begin(), [&](const char &c) { return isupper(c); });

    vi is_lower(n);

    transform(s.begin(), s.end(), is_lower.begin(), [&](const char &c) { return islower(c); });

    int min_upper = solve(k, l, is_upper);
    int min_lower = solve(k, l, is_lower);

    return min(min_upper, min_lower);
}

int main(){
#ifdef DEBUG
    assert(1 == solve(2, 2, vi({1,0,1,0,0,0,1,1,0})));
    assert(1 == solve(2, 2, "aAaAAAaaA"));
    assert(0 == solve(1, 4, "PikMike"));
    assert(2 == solve(2, 2, "AaAaAAaaAAAAaaA"));
    assert(0 == solve(2, 6, "aBcdEFGHIJklMn"));
#endif
    int n, k, l;
    string s;

    while(cin >> n >> k >> l >> s) {
        cout << solve(k, l, s) << endl;
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e6+5;

int N, K, L, H;
int awa, akh, cen, res;
int P[MAXN];
int D[MAXN];
bool A[MAXN];
bool B[MAXN];
char C;

int dp(int x) {
	for (int i=1;i<=N;i++) {
		D[i]=D[max(0,i-L)]+P[i]-P[max(0,i-L)]-x;
		B[i]=1;

		if (D[i]<=D[i-1]) {
			D[i]=D[i-1];
			B[i]=0;
		}
	}

	int ret=0;

	for (int i=N;i;i--) {
		if (B[i]) {
			ret++;
			i-=min(i,L)-1;
		}
	}

	return ret;
}

int monge() {
	for (int i=1;i<=N;i++) {
		P[i]=P[i-1]+A[i];
	}

	awa=0;
	akh=L;
	res=L;

	while (awa<=akh) {
		cen=(awa+akh)/2;

		if (dp(cen)<=K) {
			akh=cen-1;
			res=cen;
		}
		else {
			awa=cen+1;
		}
	}

	dp(res);
	return P[N]-D[N]-res*K;
}

void balik() {
	for (int i=1;i<=N;i++) {
		A[i]=!A[i];
	}

	return;
}

void input() {
	cin>>N>>K>>L;

	for (int i=1;i<=N;i++) {
		cin>>C;

		if (C>='a') {
			A[i]=1;
		}
	}

	return;
}

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

	input();
	H=monge();
	balik();
	H=min(H,monge());
	cout<<H<<'\n';

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#define isws std::ios::sync_with_stdio(false)
#define _USE_MATH_DEFINES
#define ll long long
#define ull unsigned long long

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <math.h>
#include <cmath>
#include <string>
#include <bitset>
#include <queue>

using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mt make_tuple
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef pair<int, int> pii;
const ll mod = 998244353;

const int N = 1000000 + 7;

string s;
int n, k, l;
int cum0[N], cum1[N];

pii solve0(int lambda) {
	//cout << "solve0 " << lambda << "\n";
	vector<int> dp(n + 1, 0);
	vector<int> cnt(n + 1, 0);
	for (int i = 1; i <= l; i++) {
		if (cum0[i] > lambda) {
			dp[i] = cum0[i] - lambda;
			cnt[i] = 1;
		}
	}
	for (int i = l + 1; i <= n; i++) {
		int c1 = cum0[i] - cum0[i - l] - lambda + dp[i - l];
		int c2 = dp[i - 1];
		if (c1 > c2) {
			dp[i] = c1;
			cnt[i] = cnt[i - l] + 1;
		}
		else {
			dp[i] = c2;
			cnt[i] = cnt[i - 1];
		}
	}
	//cout << dp[n] << " " << cnt[n] << "\n";
	return { dp[n], cnt[n] };
}

pii solve1(int lambda) {
	vector<int> dp(n + 1, 0);
	vector<int> cnt(n + 1, 0);
	for (int i = 1; i <= l; i++){
		if (cum1[i] > lambda) {
			dp[i] = cum1[i] - lambda;
			cnt[i] = 1;
		}
	}
	for (int i = l + 1; i <= n; i++) {
		int c1 = cum1[i] - cum1[i - l] - lambda + dp[i - l];
		int c2 = dp[i - 1];
		if (c1 > c2) {
			dp[i] = c1;
			cnt[i] = cnt[i - l] + 1;
		}
		else {
			dp[i] = c2;
			cnt[i] = cnt[i - 1];
		}
	}
	return { dp[n], cnt[n] };
}

int main()
{
	isws;
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> n >> k >> l;
	cin >> s;
	if (n * k >= l) {
		cout << 0 << "\n";
		return 0;
	}
	for (int i = 0; i < n; i++) {
		if (s[i] >= 'a' && s[i] <= 'z') cum0[i + 1]++;
		else cum1[i + 1]++;
		cum0[i + 1] += cum0[i];
		cum1[i + 1] += cum1[i];
	}
	int lo = 0, hi = n + 1;
	int ans1 = 0, ans2 = 0;
	while (lo <= hi) {
		int mid = (lo + hi) / 2;
		//cout << mid << "\n";
		pii tmp = solve0(mid);
		if (tmp.second > k) {
			lo = mid + 1;
		}
		else {
			hi = mid - 1;
			ans1 = max(ans1, tmp.first);
		}
	}
	ans1 += lo * k;
	lo = 0, hi = n + 1;
	while (lo <= hi) {
		int mid = (lo + hi) / 2;
		pii tmp = solve1(mid);
		if (tmp.second > k) {
			lo = mid + 1;
		}
		else {
			hi = mid - 1;
			ans2 = max(ans2, tmp.first);
		}
	}
	ans2 += lo * k;
	//cout << ans1 << " " << ans2 << "\n";
	cout << min(cum0[n] - ans1, cum1[n] - ans2) << "\n";
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#define isws std::ios::sync_with_stdio(false)
#define _USE_MATH_DEFINES
#define ll long long
#define ull unsigned long long

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <math.h>
#include <cmath>
#include <string>
#include <bitset>
#include <queue>

using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mt make_tuple
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef pair<int, int> pii;
const ll mod = 998244353;

const int N = 1000000 + 7;

string s;
int n, k, l;
int cum0[N], cum1[N];

pii solve0(int lambda) {
	//cout << "solve0 " << lambda << "\n";
	vector<int> dp(n + 1, 0);
	vector<int> cnt(n + 1, 0);
	for (int i = 1; i <= l; i++) {
		if (cum0[i] > lambda) {
			dp[i] = cum0[i] - lambda;
			cnt[i] = 1;
		}
	}
	for (int i = l + 1; i <= n; i++) {
		int c1 = cum0[i] - cum0[i - l] - lambda + dp[i - l];
		int c2 = dp[i - 1];
		if (c1 > c2) {
			dp[i] = c1;
			cnt[i] = cnt[i - l] + 1;
		}
		else {
			dp[i] = c2;
			cnt[i] = cnt[i - 1];
		}
	}
	//cout << dp[n] << " " << cnt[n] << "\n";
	return { dp[n], cnt[n] };
}

pii solve1(int lambda) {
	vector<int> dp(n + 1, 0);
	vector<int> cnt(n + 1, 0);
	for (int i = 1; i <= l; i++){
		if (cum1[i] > lambda) {
			dp[i] = cum1[i] - lambda;
			cnt[i] = 1;
		}
	}
	for (int i = l + 1; i <= n; i++) {
		int c1 = cum1[i] - cum1[i - l] - lambda + dp[i - l];
		int c2 = dp[i - 1];
		if (c1 > c2) {
			dp[i] = c1;
			cnt[i] = cnt[i - l] + 1;
		}
		else {
			dp[i] = c2;
			cnt[i] = cnt[i - 1];
		}
	}
	return { dp[n], cnt[n] };
}

int main()
{
	isws;
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> n >> k >> l;
	cin >> s;
	if (l * k >= n) {
		cout << 0 << "\n";
		return 0;
	}
	for (int i = 0; i < n; i++) {
		if (s[i] >= 'a' && s[i] <= 'z') cum0[i + 1]++;
		else cum1[i + 1]++;
		cum0[i + 1] += cum0[i];
		cum1[i + 1] += cum1[i];
	}
	int lo = 0, hi = n + 1;
	int ans1 = 0, ans2 = 0;
	while (lo <= hi) {
		int mid = (lo + hi) / 2;
		//cout << mid << "\n";
		pii tmp = solve0(mid);
		if (tmp.second > k) {
			lo = mid + 1;
		}
		else {
			hi = mid - 1;
			ans1 = max(ans1, tmp.first);
		}
	}
	ans1 += lo * k;
	lo = 0, hi = n + 1;
	while (lo <= hi) {
		int mid = (lo + hi) / 2;
		pii tmp = solve1(mid);
		if (tmp.second > k) {
			lo = mid + 1;
		}
		else {
			hi = mid - 1;
			ans2 = max(ans2, tmp.first);
		}
	}
	ans2 += lo * k;
	//cout << ans1 << " " << ans2 << "\n";
	cout << min(cum0[n] - ans1, cum1[n] - ans2) << "\n";
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j;
lld l,r,mid,dp[N],EPS=1e-9;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        r=N; l=0;
        while(l+EPS<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid;
        }
        ans=min(ans,round(dp[n]-r*K));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j;
lld l,r,mid,dp[N],EPS=1e-7;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        r=N; l=0;
        while(l+EPS<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid;
        }
        ans=min(ans,round(dp[n]-r*K));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j;
lld l,r,mid,dp[N],EPS=1e-6;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        r=N; l=0;
        while(l+EPS<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid;
        }
        ans=min(ans,round(dp[n]-r*K));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
lld l,r,mid,dp[N],x,y,EPS=1e-9;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans2=round(1.0*(y-x)*(K-xo)/(yo-xo)+x);
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=round(1.0*(y-x)*(K-xo)/(yo-xo)+x);
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],ans,j,l,r,mid,dp[N],x,y;
char ch;
bool s[N];

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(1,n+1) s[i]^=1;
        l=0; r=N;
        while(l<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K){
                r=mid; x=dp[n]; y=op[n];
            }
            else l=mid+1;
        }
        ans=min(ans,x-r*K);
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j,l,r,mid,dp[N],x,y;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(1,n+1) s[i]^=1;
        l=0; r=N;
        while(l<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K){
                r=mid; x=dp[n]; y=op[n];
            }
            else l=mid+1;
        }
        ans=min(ans,x-r*K);
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,ans2,uc,lc,j;
lld l,r,mid,dp[N],EPS=1e-9;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        r=N; l=0;
        while(l+EPS<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid;
        }
        ans=min(ans,dp[n]-r*K);
    }
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(K*L>=n){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(L,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]>dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            r=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            l=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-K*L+ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=0.01;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(K*L>=n){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(L,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]>dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            r=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            l=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-K*L+ans2);
    return 0;
}
/**

*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j;
double l,r,mid,dp[N],EPS=1e-7;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        r=N; l=0;
        while(l+EPS<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid;
        }
        ans=min(ans,round(dp[n]-r*K));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-9;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(K*L>=n){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(L,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]>dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            r=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            l=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-K*L+ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-6;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=(y-x)*(K-xo)/(yo-xo)+x;
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=dp[n]+op[n]*mid; yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=dp[n]+op[n]*mid; xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=(y-x)*(K-xo)/(yo-xo)+x;
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
ll n,K,L,op[N],s[N],ans,j,l,r,mid,dp[N],x;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        l=0; r=N;
        while(l<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid+1;
        }
        ans=min(ans,round(dp[n]-r*(K-op[n])));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,op[N],s[N],ans,j,l,r,mid,dp[N],x;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        l=0; r=N;
        while(l<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
           #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
ll n,K,L,op[N],s[N],ans,j,l,r,mid,dp[N],x;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; ans=inf;
    fori(1,n+1){
        cin>>ch; s[i]=(ch>='a');
    }
    fork(0,2){
        fori(0,n+1) s[i]^=1;
        l=0; r=N;
        while(l<r){
            mid=(l+r)/2;
            fori(1,n+1){
                dp[i]=dp[i-1]+s[i]; op[i]=op[i-1]; j=max(0,i-L);
                if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K) r=mid;
            else l=mid+1;
        }
        ans=min(ans,round(dp[n]-r*(K-op[n])));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/
     if(dp[i]>dp[j]+mid){
                    dp[i]=dp[j]+mid;
                    op[i]=op[j]+1;
                }
            }
            if(op[n]<=K){
                r=mid;
            }
            else l=mid+1;
        }
        ans=min(ans,round(dp[n]-r*(K-op[n])));
    }
    cout<<ans;
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<int>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct pair_hash{template<class T1,class T2> size_t operator()(const pair<T1,T2>&pair)const{return 31*hash<T1>{}(pair.first)+hash<T2>{}(pair.second);}};
struct chash{int operator()(ll x) const { x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31)+SEED;}};
#define nl "\n"

const int N=1000010,M=MOD;
int n,K,L,xo,yo,op[N],sum[N],ans,ans2,uc,lc,j;
double l,r,mid,dp[N],x,y,EPS=1e-4;
char ch;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>K>>L; r=N;
    fori(1,n+1){
        cin>>ch;
        sum[i]=sum[i-1]+(ch>='a');
        if(ch>='a') lc++;
        else uc++;
    }
    if(n<=K*L){
        cout<<0;
        return 0;
    }
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans=x;
    else ans=round(1.0*(y-x)*(K-xo)/(yo-xo)+x);
    fori(0,n+1) sum[i]=i-sum[i];
    r=N; l=0;
    while(l+EPS<r){
        mid=(l+r)/2;
        fori(1,n+1){
            dp[i]=dp[i-1]; op[i]=op[i-1]; j=max(0,i-L);
            if(dp[i]<dp[j]+sum[i]-sum[j]-mid){
                dp[i]=dp[j]+sum[i]-sum[j]-mid;
                op[i]=op[j]+1;
            }
        }
        if(op[n]>=K){
            y=round(dp[n]+op[n]*mid); yo=op[n];
            l=mid;
        }
        if(op[n]<=K){
            x=round(dp[n]+op[n]*mid); xo=op[n];
            r=mid;
        }
    }
    if(xo==yo) ans2=x;
    else ans2=round(1.0*(y-x)*(K-xo)/(yo-xo)+x);
    cout<<min(lc-ans,uc-ans2);
    return 0;
}
/**
15 2 3
XXXxxXXXxxXXXxxXXX

15 2 3
xxxXXxxxXXxxxXXxxx
*/