// 
//./D<test

#include <bits/stdc++.h>
#define endl '\\n'
#define cediv(a,b) ((a)%(b)==0?((a)/(b)):((a)/(b))+1)
#define fi first
#define se second
#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;

template<typename T>
inline T umax(T &u, T v){return u = max(u, v);}
template<typename T>
inline T umin(T &u, T v){return u = min(u, v);}

int datas[5050];
string ss[5050];
int mx[5050][5050]; // [i][j]는 [i,j]원소들의 길이의 mx값
int DP[5050];
int n, w;
int pred[5050];
vector<int> ans;
vector<int> interval;
int num[5050];
#define INF 10000

bool check(int l){
    // l is total length
    // mx에다가 1씩 더하고, 마지막에 대신 w+1과 비교하는 걸로
    bool flag=true;
    DP[0]=mx[0][0]+1;
    for(int i=1; i<n; i++){
        DP[i]=(i<l?0+mx[i][0]+1:INF);
        for(int j=max(0,i-l); j<i; j++){
            DP[i]=min(DP[i],DP[j]+mx[i][j+1]+1);
        }
    }
    if(DP[n-1]>w+1) return false;
    else return true;
}

bool check_plt(int l){
    // l is total length
    // mx에다가 1씩 더하고, 마지막에 대신 w+1과 비교하는 걸로
    bool flag=true;
    DP[0]=mx[0][0]+1;
    pred[0]=-1;
    for(int i=1; i<n; i++){
        DP[i]=(i<l?0+mx[i][0]+1:INF);
        pred[i]=-1;
        for(int j=max(0,i-l); j<i; j++){
            if(DP[i]>DP[j]+mx[i][j+1]+1){
                DP[i]=DP[j]+mx[i][j+1]+1;
                pred[i]=j;
            }
        }
    }
    if(DP[n-1]>w+1) return false;
    else return true;
}

int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    cin>>n>>w;
    for(int i=0; i<n; i++){
        cin>>ss[i];
        datas[i]=ss[i].size(); 
    }
    for(int i=0; i<n; i++){
        mx[i][i]=datas[i];
        for(int j=i+1; j<n; j++){
            mx[j][i]=max(mx[j-1][i],datas[j]);
        }   
    }  
    int l=1, r=n;
    while(l!=r){
        int mid=(l+r)>>1;
        check(mid);
        if(check(mid)) r=mid;
        else l=mid+1;
    }

    check_plt(r);
    int col=1;
    int cur=n-1;
    ans.push_back(cur);
    while(pred[cur]!=-1){
        cur=pred[cur];
        col++;
        ans.push_back(cur);
    }
    reverse(ans.begin(), ans.end());
    int last=0;
    for(int i=0; i<ans.size(); i++){
        interval.push_back(mx[ans[i]][last]+1);
        last=ans[i]+1;
    }
    cout<<r<<' '<<col<<endl;
    for(int i=0; i<interval.size(); i++) cout<<interval[i]-1<<' ';
    cout<<endl;
    for(int i=0; i<col; i++) num[i]=(i==0?0:ans[i-1]+1);
    for(int i=0; i<r; i++){
        for(int j=0; j<col; j++){
            if(num[j]>ans[j]){
                for(int k=0; k<interval[j]; k++) cout<<' ';
            }
            else{
                cout<<ss[num[j]];
                for(int k=0; k<interval[j]-ss[num[j]].size(); k++) cout<<' ';
                num[j]++;   
            }
        }
        cout<<endl;
    }
    return 0;
}