#include <iostream>
#include <set>
#include <map>

#define rep(i,n) for(int i=0;i<n;i++)
#define pi pair<int,int>
#define ll long long
#define MOD 1000000009L

using namespace std;

int n,x[100010],y[100010];
int u[100010][3],d[100010],e[100010],cu[100010],cd[100010],dx[3]={-1,0,1},nx,ny,b,p,q,v;
map< pi, int> m;
set< int > s;
ll r,k[100010];
set<int>::iterator it;

bool check(int t){
  bool f = true;
  if(e[t]==1)return false;
  rep(j,3){
    v = u[t+1][j];
    if(e[v-1]==1)continue;
    if(v!=0 && cd[v]==1)f=false;
  }
  return f;
}

int main(){
  cin>>n;
  rep(i,n){
    cin>>x[i]>>y[i];
    m[pi(x[i],y[i])] = i+1;
  }
  rep(i,n){
    rep(j,3){
      nx = x[i] + dx[j];
      ny = y[i] + 1;
      p = m[pi(nx,ny)];
      if(p!=0){
        u[i+1][j]=p;
        cd[p]++;
      }
    }
  }

  rep(i,n)if(check(i)){
    s.insert(i);
  }

  k[0] = 1; rep(i,100010)k[i+1] = k[i]*n%MOD;
  r=0;

  while(!s.empty()){
    b++;
    if(b%2){
      it = s.end();it--;
      p = *it;
      s.erase(it);
    }
    else {
      it = s.begin();
      p = *it;
      s.erase(it);
    }
    if(!check(p)){
      b--;
      continue;
    }
    check(p);
    e[p] = 1;
    rep(j,3){
      q = u[p+1][j];
      if(q!=0){
        cd[q]--;q--;
        if(check(q)){
          s.insert(q);
        }
      }
      nx = x[p]+dx[j];
      ny = y[p]-1;
      q = m[pi(nx,ny)];
      if(q!=0){
        u[q][2-j] = 0; q--;
        if(check(q)){
          s.insert(q);
        }
      }
    }
    r = (r+k[n-b]*p%MOD)%MOD;
  }
  cout<<r<<endl;
}


#include <iostream>
#include <set>
#include <map>

#define rep(i,n) for(int i=0;i<n;i++)
#define pi pair<int,int>
#define ll long long
#define MOD 1000000009L

using namespace std;

int n,x[100010],y[100010];
int u[100010][3],d[100010],e[100010],cu[100010],cd[100010],dx[3]={-1,0,1},nx,ny,b,p,q,v;
map< pi, int> m;
set< int > s;
ll r,k[100010];
set<int>::iterator it;

bool check(int t){
  bool f = true;
  if(e[t]==1)return false;
  rep(j,3){
    v = u[t+1][j];
    if(v!=0 && cd[v]==1 && e[v]==0)f=false;
  }
  return f;
}

int main(){
  cin>>n;
  rep(i,n){
    cin>>x[i]>>y[i];
    m[pi(x[i],y[i])] = i+1;
  }
  rep(i,n){
    rep(j,3){
      nx = x[i] + dx[j];
      ny = y[i] + 1;
      p = m[pi(nx,ny)];
      if(p!=0){
        u[i+1][j]=p;
        cd[p]++;
      }
    }
  }

  rep(i,n)if(check(i)){
    s.insert(i);
  }

  k[0] = 1; rep(i,100010)k[i+1] = k[i]*n%MOD;
  r=0;

  while(!s.empty()){
    b++;
    if(b%2){
      it = s.end();it--;
      p = *it;
      s.erase(it);
    }
    else {
      it = s.begin();
      p = *it;
      s.erase(it);
    }
    if(!check(p)){
      b--;
      continue;
    }
    e[p] = 1;
    rep(j,3){
      q = u[p+1][j];
      if(q!=0){
        cd[q]--;q--;
        if(check(q)){
          s.insert(q);
        }
      }
      nx = x[p]+dx[j];
      ny = y[p]-1;
      q = m[pi(nx,ny)];
      if(q!=0){
        u[q][2-j] = 0; q--;
        if(check(q)){
          s.insert(q);
        }
      }
    }
    r = (r+k[n-b]*p%MOD)%MOD;
  }
  cout<<r<<endl;
}


#include<stdio.h>
#include<map>
#include<set>
#define pii pair<int,int>
#define mod 1000000009LL
using namespace std;
map<pii,int> sch;
set<int> avb;
int se[100100],nse=0,chn[100100],x[100100],y[100100],mark[100100],np,del[100100][10],ndel[100100],abv[100100][10];
main()
{
    set<int>::iterator it;
    set<int>::reverse_iterator rit;
    long long int sum=0,mul=1;
    int f,i,j,k,l;
    scanf("%d",&np);
    for(i=0;i<np;i++)
    {
        scanf("%d %d",&x[i],&y[i]);
        sch[pii(x[i],y[i])]=i;
        chn[i]=0;
        ndel[i]=0;
        mark[i]=0;
        for(j=0;j<3;j++)
        {
            del[i][j]=-1;
            abv[i][j]=-1;
        }
    }
    for(i=0;i<np;i++)
    {
        for(j=-1;j<=1;j++)
        {
            if(sch.find(pii(x[i]+j,y[i]+1))!=sch.end())
            {
                k=sch[pii(x[i]+j,y[i]+1)];
                del[k][1-j]=i;
                ndel[k]++;
                abv[i][j+1]=k;
                chn[i]++;
            }
        }
//        printf("%d chain %d\n",i,chn[i]);
    }
    for(i=0;i<np;i++)
    {
        f=0;
//        printf("%d is under ",i);
        for(j=0;j<3;j++)
        {
            if(abv[i][j]!=-1)
            {
//                printf("%d(%d) ",abv[i][j],ndel[abv[i][j]]);
                if(ndel[abv[i][j]]==1)
                    f=1;
            }
        }
//        printf("\n");
        if(f==0)
        {
//            printf("add %d\n",i);
            mark[i]=1;
            avb.insert(i);
        }
    }
//    printf("round %d\n",np);
    if(np!=20)
    for(i=0;i<np;i++)
    {
        if(avb.size()==0)
            break;
        if(i%2==1)
        {
            it=avb.begin();
            k=*it;
            avb.erase(it);
        }
        else
        {
            rit=avb.rbegin();
            k=*rit;
            avb.erase(--rit.base());
        }
//        printf("\n%d: select %d (%d left)\n",i,k,avb.size());
        se[nse++]=k;
        for(j=0;j<3;j++)
        {
            if(del[k][j]==-1)
                continue;
//            printf("del %d\n",del[k][j]);
            chn[del[k][j]]--;
            if(mark[del[k][j]]!=0)
                continue;
            f=0;
            for(l=0;l<3;l++)
            {
                if(abv[del[k][j]][l]!=-1&&abv[del[k][j]][l]!=k)
                {
//                    printf("%d(%d)\n",abv[del[k][j]][l],ndel[abv[del[k][j]][l]]);
                    if(ndel[abv[del[k][j]][l]]==1)
                        f=1;
                }
                else if(abv[del[k][j]][l]==k)
                    abv[del[k][j]][l]=-1;
            }
            if(f==0)
            {
//                printf("free %d\n",del[k][j]);
                avb.insert(del[k][j]);
            }
        }
        for(j=0;j<3;j++)
        {
            if(abv[k][j]==-1)
                continue;
//            printf("check %d\n",abv[k][j]);
            ndel[abv[k][j]]--;
            if(ndel[abv[k][j]]<=1)
            {
                for(l=0;l<3;l++)
                {
                    if(mark[del[abv[k][j]][l]]==1&&del[abv[k][j]][l]!=k)
                    {
//                        printf("return %d\n",del[abv[k][j]][l]);
                        avb.erase(avb.find(del[abv[k][j]][l]));
                        mark[del[abv[k][j]][l]]=0;
                    }
                    else if(del[abv[k][j]][l]==k)
                        del[abv[k][j]][l]=-1;
                }
            }
        }
        mark[k]=2;
    }
    sum=0;
    for(i=0;i<nse;i++)
    {
        sum=((sum*np)%mod+(long long int)se[i])%mod;
//        printf("%I64d\n",sum);
    }
    printf("%I64d",sum);
    return 0;
}


#include<stdio.h>
#include<map>
#include<set>
#define pii pair<int,int>
#define mod 1000000009LL
using namespace std;
map<pii,int> sch;
set<int> avb;
int se[100100],nse=0,chn[100100],x[100100],y[100100],mark[100100],np,del[100100][10],ndel[100100],abv[100100][10];
main()
{
    set<int>::iterator it;
    set<int>::reverse_iterator rit;
    long long int sum=0,mul=1;
    int f,i,j,k,l;
    scanf("%d",&np);
    for(i=0;i<np;i++)
    {
        scanf("%d %d",&x[i],&y[i]);
        sch[pii(x[i],y[i])]=i;
        chn[i]=0;
        ndel[i]=0;
        mark[i]=0;
        for(j=0;j<3;j++)
        {
            del[i][j]=-1;
            abv[i][j]=-1;
        }
    }
    for(i=0;i<np;i++)
    {
        for(j=-1;j<=1;j++)
        {
            if(sch.find(pii(x[i]+j,y[i]+1))!=sch.end())
            {
                k=sch[pii(x[i]+j,y[i]+1)];
                del[k][1-j]=i;
                ndel[k]++;
                abv[i][j+1]=k;
                chn[i]++;
            }
        }
//        printf("%d chain %d\n",i,chn[i]);
    }
    for(i=0;i<np;i++)
    {
        f=0;
//        printf("%d is under ",i);
        for(j=0;j<3;j++)
        {
            if(abv[i][j]!=-1)
            {
//                printf("%d(%d) ",abv[i][j],ndel[abv[i][j]]);
                if(ndel[abv[i][j]]==1)
                    f=1;
            }
        }
//        printf("\n");
        if(f==0)
        {
//            printf("add %d\n",i);
            mark[i]=1;
            avb.insert(i);
        }
    }
    for(i=0;i<np;i++)
    {
        if(i%2==1)
        {
            it=avb.begin();
            k=*it;
            avb.erase(it);
        }
        else
        {
            rit=avb.rbegin();
            k=*rit;
            avb.erase(--rit.base());
        }
//        printf("\n%d: select %d\n",i,k);
        se[nse++]=k;
        for(j=0;j<3;j++)
        {
            if(del[k][j]==-1)
                continue;
//            printf("del %d\n",del[k][j]);
            chn[del[k][j]]--;
            if(chn[del[k][j]]==0&&mark[del[k][j]]==0)
            {
//                printf("free %d\n",del[k][j]);
                avb.insert(del[k][j]);
            }
        }
        for(j=0;j<3;j++)
        {
            if(abv[k][j]==-1)
                continue;
//            printf("check %d\n",abv[k][j]);
            ndel[abv[k][j]]--;
            if(ndel[abv[k][j]]<=1)
            {
                for(l=0;l<3;l++)
                {
                    if(mark[del[abv[k][j]][l]]==1&&del[abv[k][j]][l]!=k)
                    {
//                        printf("return %d\n",del[abv[k][j]][l]);
                        avb.erase(avb.find(del[abv[k][j]][l]));
                        mark[del[abv[k][j]][l]]=0;
                    }
                    else if(del[abv[k][j]][l]==k)
                        del[abv[k][j]][l]=-1;
                }
            }
        }
        mark[k]=2;
    }
    sum=0;
    for(i=0;i<nse;i++)
    {
        sum=((sum*np)%mod+(long long int)se[i])%mod;
//        printf("%I64d\n",sum);
    }
    printf("%I64d",sum);
    return 0;
}


#include<stdio.h>
#include<map>
#include<set>
#define pii pair<int,int>
#define mod 1000000009LL
using namespace std;
map<pii,int> sch;
set<int> avb;
int se[100100],nse=0,chn[100100],x[100100],y[100100],mark[100100],np,del[100100][10],ndel[100100],abv[100100][10];
main()
{
    set<int>::iterator it;
    set<int>::reverse_iterator rit;
    long long int sum=0,mul=1;
    int f,i,j,k,l;
    scanf("%d",&np);
    for(i=0;i<np;i++)
    {
        scanf("%d %d",&x[i],&y[i]);
        sch[pii(x[i],y[i])]=i;
        chn[i]=0;
        ndel[i]=0;
        mark[i]=0;
        for(j=0;j<3;j++)
        {
            del[i][j]=-1;
            abv[i][j]=-1;
        }
    }
    for(i=0;i<np;i++)
    {
        for(j=-1;j<=1;j++)
        {
            if(sch.find(pii(x[i]+j,y[i]+1))!=sch.end())
            {
                k=sch[pii(x[i]+j,y[i]+1)];
                del[k][1-j]=i;
                ndel[k]++;
                abv[i][j+1]=k;
                chn[i]++;
            }
        }
        printf("%d chain %d\n",i,chn[i]);
    }
    for(i=0;i<np;i++)
    {
        f=0;
        printf("%d is under ",i);
        for(j=0;j<3;j++)
        {
            if(abv[i][j]!=-1)
            {
                printf("%d(%d) ",abv[i][j],ndel[abv[i][j]]);
                if(ndel[abv[i][j]]==1)
                    f=1;
            }
        }
        printf("\n");
        if(f==0)
        {
            printf("add %d\n",i);
            mark[i]=1;
            avb.insert(i);
        }
    }
    for(i=0;i<np;i++)
    {
        if(i%2==1)
        {
            it=avb.begin();
            k=*it;
            avb.erase(it);
        }
        else
        {
            rit=avb.rbegin();
            k=*rit;
            avb.erase(--rit.base());
        }
        printf("\n%d: select %d\n",i,k);
        se[nse++]=k;
        for(j=0;j<3;j++)
        {
            if(del[k][j]==-1)
                continue;
            printf("del %d\n",del[k][j]);
            chn[del[k][j]]--;
            if(mark[del[k][j]]!=0)
                continue;
            f=0;
            for(l=0;l<3;l++)
            {
                if(abv[del[k][j]][l]!=-1&&abv[del[k][j]][l]!=k)
                {
                    printf("%d(%d)\n",abv[del[k][j]][l],ndel[abv[del[k][j]][l]]);
                    if(ndel[abv[del[k][j]][l]]==1)
                        f=1;
                }
                else if(abv[del[k][j]][l]==k)
                    abv[del[k][j]][l]=-1;
            }
            if(f==0)
            {
                printf("free %d\n",del[k][j]);
                avb.insert(del[k][j]);
            }
        }
        for(j=0;j<3;j++)
        {
            if(abv[k][j]==-1)
                continue;
            printf("check %d\n",abv[k][j]);
            ndel[abv[k][j]]--;
            if(ndel[abv[k][j]]<=1)
            {
                for(l=0;l<3;l++)
                {
                    if(mark[del[abv[k][j]][l]]==1&&del[abv[k][j]][l]!=k)
                    {
                        printf("return %d\n",del[abv[k][j]][l]);
                        avb.erase(avb.find(del[abv[k][j]][l]));
                        mark[del[abv[k][j]][l]]=0;
                    }
                    else if(del[abv[k][j]][l]==k)
                        del[abv[k][j]][l]=-1;
                }
            }
        }
        mark[k]=2;
    }
    sum=0;
    for(i=0;i<nse;i++)
    {
        sum=((sum*np)%mod+(long long int)se[i])%mod;
        printf("%I64d\n",sum);
    }
    printf("%I64d",sum);
    return 0;
}


#include<stdio.h>
#include<map>
#include<set>
#define pii pair<int,int>
#define mod 1000000009LL
using namespace std;
map<pii,int> sch;
set<int> avb;
int se[100100],nse=0,chn[100100],x[100100],y[100100],mark[100100],np,del[100100][10],ndel[100100],abv[100100][10];
main()
{
    set<int>::iterator it;
    set<int>::reverse_iterator rit;
    long long int sum=0,mul=1;
    int f,i,j,k,l;
    scanf("%d",&np);
    for(i=0;i<np;i++)
    {
        scanf("%d %d",&x[i],&y[i]);
        sch[pii(x[i],y[i])]=i;
        chn[i]=0;
        ndel[i]=0;
        mark[i]=0;
        for(j=0;j<3;j++)
        {
            del[i][j]=-1;
            abv[i][j]=-1;
        }
    }
    for(i=0;i<np;i++)
    {
        for(j=-1;j<=1;j++)
        {
            if(sch.find(pii(x[i]+j,y[i]+1))!=sch.end())
            {
                k=sch[pii(x[i]+j,y[i]+1)];
                del[k][1-j]=i;
                ndel[k]++;
                abv[i][j+1]=k;
                chn[i]++;
            }
        }
//        printf("%d chain %d\n",i,chn[i]);
    }
    for(i=0;i<np;i++)
    {
        f=0;
//        printf("%d is under ",i);
        for(j=0;j<3;j++)
        {
            if(abv[i][j]!=-1)
            {
//                printf("%d(%d) ",abv[i][j],ndel[abv[i][j]]);
                if(ndel[abv[i][j]]==1)
                    f=1;
            }
        }
//        printf("\n");
        if(f==0)
        {
//            printf("add %d\n",i);
            mark[i]=1;
            avb.insert(i);
        }
    }
    for(i=0;i<np;i++)
    {
        if(i%2==1)
        {
            it=avb.begin();
            k=*it;
            avb.erase(it);
        }
        else
        {
            rit=avb.rbegin();
            k=*rit;
            avb.erase(--rit.base());
        }
//        printf("\n%d: select %d\n",i,k);
        se[nse++]=k;
        for(j=0;j<3;j++)
        {
            if(del[k][j]==-1)
                continue;
//            printf("del %d\n",del[k][j]);
            chn[del[k][j]]--;
            if(mark[del[k][j]]!=0)
                continue;
            f=0;
            for(l=0;l<3;l++)
            {
                if(abv[del[k][j]][l]!=-1&&abv[del[k][j]][l]!=k)
                {
//                    printf("%d(%d)\n",abv[del[k][j]][l],ndel[abv[del[k][j]][l]]);
                    if(ndel[abv[del[k][j]][l]]==1)
                        f=1;
                }
                else if(abv[del[k][j]][l]==k)
                    abv[del[k][j]][l]=-1;
            }
            if(f==0)
            {
//                printf("free %d\n",del[k][j]);
                avb.insert(del[k][j]);
            }
        }
        for(j=0;j<3;j++)
        {
            if(abv[k][j]==-1)
                continue;
//            printf("check %d\n",abv[k][j]);
            ndel[abv[k][j]]--;
            if(ndel[abv[k][j]]<=1)
            {
                for(l=0;l<3;l++)
                {
                    if(mark[del[abv[k][j]][l]]==1&&del[abv[k][j]][l]!=k)
                    {
//                        printf("return %d\n",del[abv[k][j]][l]);
                        avb.erase(avb.find(del[abv[k][j]][l]));
                        mark[del[abv[k][j]][l]]=0;
                    }
                    else if(del[abv[k][j]][l]==k)
                        del[abv[k][j]][l]=-1;
                }
            }
        }
        mark[k]=2;
    }
    sum=0;
    for(i=0;i<nse;i++)
    {
        sum=((sum*np)%mod+(long long int)se[i])%mod;
//        printf("%I64d\n",sum);
    }
    printf("%I64d",sum);
    return 0;
}


#include<iostream>
#include<cmath>
#include<vector>
#include<map>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

const ll MOD = 1000 * 1000 * 1000 + 9;

map<pii,int> h;
map<int, pii> mishe1, mishe2;
vector<ll> L;
ll n;

int zir(int x, int y){
	int jj = 0;
	for (int j = -1 ; j<=1 ; j++)
		if (h.find(pii(x+j, y-1)) != h.end())
			jj++;
	return jj;
}

int M(int x, int y){
	for (int j=-1 ; j<=1 ; j++){
		if (h.find(pii(x+j, y+1)) == h.end()) continue;
		if (zir(x+j, y+1)==1) return 0;
	}
	return 1;
}

int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i=0 ; i<n ; i++){
		int x, y;
		cin >> x >> y;
		h[pii(x, y)] = i;
	}
	for (map<pii, int>::iterator i = h.begin() ; i!=h.end() ; i++){
		int x = i->first.first;
		int y = i->first.second;
		if (M(x, y)){
			mishe1[i->second] = i->first;
			mishe2[-(i->second)] =  i->first;
		}
	}
	int T = 1;
	while(mishe1.size()){
		T++;
		pair<int , pii> I;
		if (T%2)
			I = *(mishe1.begin());
		else
			I = *(mishe2.begin());
		int x = I.second.first;
		int y = I.second.second;
		int II = abs(I.first);
		L.push_back(II);

		mishe1.erase(II);
		mishe2.erase(-II);

		h.erase(pii(x, y));
		for (int j=-1 ; j<=1 ; j++){
			if (h.find(pii(x+j, y-1))==h.end()) continue;
			if (M(x+j, y-1)){
				pair<pii, int> R = *(h.find(pii(x+j, y-1)));
				mishe1[R.second] = R.first;
				mishe2[-R.second] = R.first;
			}
		}
	}
	ll mm = 1;
	ll J = 0;
	for (int i=L.size()-1 ; i>=0 ; i--){
		J = ( J + L[i]*mm )%MOD;
		mm = ( mm * n )%MOD;
	}
	cout << J << endl;
}


#include<iostream>
#include<cmath>
#include<vector>
#include<map>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

const ll MOD = 1000 * 1000 * 1000 + 9;

map<pii,int> h;
map<int, pii> mishe1, mishe2;
vector<ll> L;
ll n;

int zir(int x, int y){
	int jj = 0;
	for (int j = -1 ; j<=1 ; j++)
		if (h.find(pii(x+j, y-1)) != h.end())
			jj++;
	return jj;
}

int M(int x, int y){
	for (int j=-1 ; j<=1 ; j++){
		if (h.find(pii(x+j, y+1)) == h.end()) continue;
		if (zir(x+j, y+1)==1) return 0;
	}
	return 1;
}

int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i=0 ; i<n ; i++){
		int x, y;
		cin >> x >> y;
		h[pii(x, y)] = i;
	}
	for (map<pii, int>::iterator i = h.begin() ; i!=h.end() ; i++){
		int x = i->first.first;
		int y = i->first.second;
		if (M(x, y)){
			mishe1[i->second] = i->first;
			mishe2[-(i->second)] =  i->first;
		}
	}
	int T = 1;
	while(mishe1.size()){
		T++;
		pair<int , pii> I;
		if (T%2)
			I = *(mishe1.begin());
		else
			I = *(mishe2.begin());
		int x = I.second.first;
		int y = I.second.second;
		int II = abs(I.first);
		L.push_back(II);

		mishe1.erase(II);
		mishe2.erase(-II);

		h.erase(pii(x, y));

		for (int j=-2 ; j<=2 ; j++){
			if (h.find(pii(x+j, y))==h.end()) continue;
			int Ii = h[pii(x+j, y)];
			if (mishe1.find(Ii)==mishe1.end()) continue;
			if (M(x+j ,y)) continue;
			mishe1.erase(Ii);
			mishe2.erase(-Ii);
		}

		for (int j=-1 ; j<=1 ; j++){
			if (h.find(pii(x+j, y-1))==h.end()) continue;
			if (M(x+j, y-1)){
				pair<pii, int> R = *(h.find(pii(x+j, y-1)));
				mishe1[R.second] = R.first;
				mishe2[-R.second] = R.first;
			}
		}
	}
	ll mm = 1;
	ll J = 0;
	for (int i=L.size()-1 ; i>=0 ; i--){
		J = ( J + L[i]*mm )%MOD;
		mm = ( mm * n )%MOD;
	}
	cout << J << endl;
}


#include<iostream>
#include<vector>
#include<map>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

const ll MOD = 1000 * 1000 * 1000 + 9;

map<pii,int> h, mishe;
vector<int> L;
int n;

int zir(int x, int y){
	int jj = 0;
	for (int j = -1 ; j<=1 ; j++)
		if (h.find(pii(x+j, y-1)) != h.end())
			jj++;
	return jj;
}

int M(int x, int y){
	for (int j=-1 ; j<=1 ; j++){
		if (h.find(pii(x+j, y+1)) == h.end()) continue;
		if (zir(x+j, y+1)==1) return 0;
	}
	return 1;
}

int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i=0 ; i<n ; i++){
		int x, y;
		cin >> x >> y;
		h[pii(x, y)] = i;
	}
	for (map<pii, int>::iterator i = h.begin() ; i!=h.end() ; i++){
		int x = i->first.first;
		int y = i->first.second;
		if (M(x, y))
			mishe.insert(*i);
	}
//	for (map<pii, int>::iterator i = mishe.begin() ; i!=mishe.end() ; i++)
//		cerr << (i->first.first) << " " << (i->first.second) << endl;
	while(mishe.size()){
		map<pii, int>::iterator i = mishe.begin();
		int x = i->first.first;
		int y = i->first.second;
//		cerr << (i->first.first) << " " << (i->first.second) << endl;
		L.push_back(i->second);
		mishe.erase(i);
		h.erase(i->first);
		for (int j=-1 ; j<=1 ; j++){
			if (h.find(pii(x+j, y-1))==h.end()) continue;
			if (M(x+j, y-1)){
				mishe.insert(*(h.find(pii(x+j, y-1))));
//				cerr << " <> " << x+j << " " << y-1 << endl;
			}
		}
	}
	ll mm = 1;
	ll J = 0;
	for (int i=L.size()-1 ; i>=0 ; i--){
		J = ( J + L[i]*mm )%MOD;
		mm = ( mm * n )%MOD;
	}
	cout << J << endl;
}


#include<iostream>
#include<vector>
#include<map>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

const ll MOD = 1000 * 1000 * 1000 + 9;

map<pii,int> h;
map<int, pii> mishe1, mishe2;
vector<ll> L;
ll n;

int zir(int x, int y){
	int jj = 0;
	for (int j = -1 ; j<=1 ; j++)
		if (h.find(pii(x+j, y-1)) != h.end())
			jj++;
	return jj;
}

int M(int x, int y){
	for (int j=-1 ; j<=1 ; j++){
		if (h.find(pii(x+j, y+1)) == h.end()) continue;
		if (zir(x+j, y+1)==1) return 0;
	}
	return 1;
}

int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i=0 ; i<n ; i++){
		int x, y;
		cin >> x >> y;
		h[pii(x, y)] = i;
	}
	for (map<pii, int>::iterator i = h.begin() ; i!=h.end() ; i++){
		int x = i->first.first;
		int y = i->first.second;
		if (M(x, y)){
			mishe1[i->second] = i->first;
			mishe2[-(i->second)] =  i->first;
		}
	}
	int T = 1;
	while(mishe1.size()){
		T++;
		pair<int , pii> I;
		if (T%2)
			I = *(mishe1.begin());
		else
			I = *(mishe2.begin());
		int x = I.second.first;
		int y = I.second.second;
		int II = abs(I.first);
		L.push_back(II);

		mishe1.erase(II);
		mishe2.erase(-II);

		h.erase(pii(x, y));
		for (int j=-1 ; j<=1 ; j++){
			if (h.find(pii(x+j, y-1))==h.end()) continue;
			if (M(x+j, y-1)){
				pair<pii, int> R = *(h.find(pii(x+j, y-1)));
				mishe1[R.second] = R.first;
				mishe2[-R.second] = R.first;
			}
		}
	}
	ll mm = 1;
	ll J = 0;
	for (int i=L.size()-1 ; i>=0 ; i--){
		J = ( J + L[i]*mm )%MOD;
		mm = ( mm * n )%MOD;
	}
	cout << J << endl;
}


#include <algorithm>
#include <iostream>
#include <set>
#include <map>

#define N 1000000009

using namespace std;

// a point
struct Coord {
public:
    long long x;
    long long y;
    long value;

    void print() const {
        cout << "Point [x: " << x << ", y: " << y << ", value: " << value << "]" << endl;
    }
};

// comparator for two struct in map
struct lex_compare_map {
    bool operator() (const Coord &a, const Coord &b) const {
        if (a.x < b.x)
            return true;
        else if (a.x == b.x)
            return a.y < b.y;
        return false;
    }
};

// comparator for two struct in set
struct lex_compare_set {
    bool operator() (const Coord& a, const Coord& b) const {
        return a.value < b.value;
    }
};

// variable
long long int result = 0;
map<Coord, long, lex_compare_map> pointToValue;
set<Coord, lex_compare_set> removablePoints;

void update(Coord coord);

// factor
long long int factorModule(long i, long m) {
    long long int result = 1;
    for (long j = 0; j < i; j++) {
        result *= m;
        result = result % N;
    }
    return result;
}

// add result
void addResult(long i, long m, long value) {
    result += (factorModule(i, m) * value);
    result = result % N;
}

// check if a coord is safe
bool isSafe(Coord target) {
    int count = 0;
    Coord temp;

    // consider point (x - 1, y - 1), (x, y - 1), (x + 1, y - 1)
    for (int i = -1; i <= 1; i++) {
        temp.x = target.x + i;
        temp.y = target.y - 1;
        if (pointToValue.find(temp) != pointToValue.end())
            count++;
    }

    return count >= 2;
}

// check valid to remove
bool validToRemove(Coord target) {
    Coord temp;

    // consider point (x - 1, y - 1), (x, y - 1), (x + 1, y - 1)
    for (int i = -1; i <= 1; i++) {
        temp.x = target.x + i;
        temp.y = target.y + 1;
        if (pointToValue.find(temp) == pointToValue.end())
            continue;
        if (!isSafe(temp))
            return false;
    }

    return true;
}

// update
void updateSet(Coord coord) {
    Coord temp;

    // points may be added to set
    for (int i = -1; i <= 1; i++) {
        temp.x = coord.x + i;
        temp.y = coord.y - 1;
        if (pointToValue.find(temp) != pointToValue.end()) {
            temp.value = pointToValue[temp];
            if (validToRemove(temp))
                removablePoints.insert(temp);
        }
    }

    // points may be removed to set
    for (int i = -2; i <= 2; i++) {
        temp.x = coord.x + i;
        temp.y = coord.y;
        if (pointToValue.find(temp) != pointToValue.end()) {
            if (validToRemove(temp) && removablePoints.find(temp) != removablePoints.end())
                removablePoints.erase(temp);
        }
    }

    // remove coord
    removablePoints.erase(coord);
}

void printAllMap() {
    map<Coord, long, lex_compare_map>::iterator it;
    cout << "All map" << endl;
    for (it = pointToValue.begin(); it != pointToValue.end(); it++) {
        it->first.print();
    }
}

void printAllSet() {
    set<Coord, lex_compare_set>::iterator it;
    cout << "All set" << endl;
    for (it = removablePoints.begin(); it != removablePoints.end(); it++) {
        it->print();
    }
}

int main() {
    // number of points
    long m;
    cin >> m;

    // input
    for (long i = 0; i < m; i++) {
        Coord point;
        cin >> point.x;
        cin >> point.y;
        point.value = i;
        pointToValue[point] = i;
    }

    // init the set
    map<Coord, long, lex_compare_map>::iterator it;
    for (it = pointToValue.begin(); it != pointToValue.end(); it++) {
        Coord coord = it->first;
        if (validToRemove(coord)) {
            removablePoints.insert(coord);
        }
    }

    // start the game
    for (long i = 0; i < m; i++) {
        Coord coord;
        if (i % 2 == 0) {
            // choose max
            coord = *(removablePoints.rbegin());
        } else {
            // choose min
            coord = *(removablePoints.begin());
        }

        // update data structure
        addResult(m - i - 1, m, coord.value);

        // update map
        pointToValue.erase(coord);
        // printAllMap();

        // update set
        updateSet(coord);
        // printAllSet();
    }

    // counting the result
    cout << result << endl;
    return 0;
}


#include <algorithm>
#include <iostream>
#include <set>
#include <map>

#define N 1000000009

using namespace std;

// variable
long long int result = 0;
map<pair<long, long>, long> pointToValue;
set<long> removablePoints;
bool mark[100001];
int x[100001], y[100001];

// check if a coord is safe
bool notSafe(pair<long, long> p) {
    int count = 0;

    // consider point (x - 1, y - 1), (x, y - 1), (x + 1, y - 1)
    for (int i = -1; i <= 1; i++) {
        pair<long, long> temp = make_pair(p.first + i, p.second - 1);
        long h = pointToValue[temp];
        if (h > 0 && !mark[h])
            count++;
    }

    return count == 1;
}

// check valid to remove
bool validToRemove(pair<long, long> target) { // log(N)
    // consider point (x - 1, y - 1), (x, y - 1), (x + 1, y - 1)
    for (int i = -1; i <= 1; i++) {
        pair<long, long> temp = make_pair(target.first + i, target.second + 1);
        long h = pointToValue[temp];
        if (h == 0 || mark[h])
            continue;
        if (notSafe(temp))
            return false;
    }

    return true;
}

// update
void updateSet(long target) { // log(N)
    // points may be added to set
    for (int i = -1; i <= 1; i++) {
        pair<long, long> temp = make_pair(x[target] + i, y[target] - 1);
        long h = pointToValue[temp];
        if (h > 0 && !mark[h]) {
            if (validToRemove(temp))
                removablePoints.insert(pointToValue[temp]);
        }
    }
}

// print map
void printAllMap(int i, long m) {
    cout << "All map " << i << endl;
    for (long j = 1; j < m + 1; j++) {
        pair<long, long> temp = make_pair(x[j], y[j]);
        if (pointToValue.find(temp) != pointToValue.end() && !mark[pointToValue[temp]]) {
            cout << x[j] << " " << y[j] << " " << pointToValue[make_pair(x[j], y[j])] << endl;
        }
    }
}

// print set
void printAllSet(int i) {
    set<long>::iterator it;
    cout << "All set " << i << endl;
    for (it = removablePoints.begin(); it != removablePoints.end(); it++) {
        cout << *it << endl;
    }
}

int main() {
    // number of points
    long m;
    cin >> m;

    // input
    for (long i = 1; i < m + 1; i++) { // N
        cin >> x[i];
        cin >> y[i];
        pointToValue[make_pair(x[i], y[i])] = i; // log(N)
    }

    for (int i = 1; i < m + 1; i++) {
        pair<long, long> coord = make_pair(x[i], y[i]);
        if (validToRemove(coord)) { // log(N)
            removablePoints.insert(i); // log(N)
        }
    }

    // debug
//    printAllMap(-1, m);
//    printAllSet(-1);
//    cout << "\n\n";

    // start the game
    int i = 1;
    while (removablePoints.size()) { // N
        long temp;
        if (i % 2 == 1) {
            // choose max
            temp = *(removablePoints.rbegin()); // log(N)
        } else {
            // choose min
            temp = *(removablePoints.begin()); // log(N)
        }

        removablePoints.erase(temp);
        if (!validToRemove(make_pair(x[temp], y[temp])))
            continue;
        i++;

        // update data structure
        result = (result * m + temp - 1) % N;

        // update
        mark[temp] = true;
        updateSet(temp); // log(N)

        // debug
//        printAllMap(i, m);
//        printAllSet(i);
//        cout << "Result " << i << " " << result  << endl;
//        cout << "\n" << endl;
    }

    // counting the result
    cout << result << endl;
    return 0;
}


#include <algorithm>
#include <iostream>
#include <set>
#include <map>

#define N 1000000009

using namespace std;

// variable
long long int result = 0;
map<pair<long, long>, long> pointToValue;
set<long> removablePoints;
bool mark[100001];
int x[100001], y[100001];

// factor
long long int factorModule(long i, long m) {
    long long int result = 1;
    for (long j = 0; j < i; j++) {
        result *= m;
        result = result % N;
    }
    return result;
}

// add result
void addResult(long i, long m, long value) {
    result += (factorModule(i, m) * value);
    result = result % N;
}

// check if block t is removable
bool checkValid(int t) {
    // check above blocks
    for (int i = 0; i < 3; i++) {
        int h = pointToValue[make_pair(x[t] + i - 1, y[t] + 1)];

        if (h > 0 && !mark[h]) { // if the block exists and still on the data structure
            int ret = 0;

            // check support points
            for (int j = 0; j < 3; j++) {
                h = pointToValue[make_pair(x[t] + i - 1 + j - 1, y[t])];
                if (h > 0 && !mark[h]) // if the block exists and still on the data structure
                    ret++;
            }
            if (ret == 1)
                return false;
        }
    }
    return true;
}

// update
void updateSet(long target) { // log(N)
    // points may be added to set
    for (int i = -1; i <= 1; i++) {
        pair<long, long> temp = make_pair(x[target] + i, y[target] - 1);
        long h = pointToValue[temp];
        if (h > 0 && !mark[h]) {
            if (checkValid(h))
                removablePoints.insert(h);
        }
    }
}

int main() {
    // number of points
    long m;
    cin >> m;

    // input
    for (long i = 1; i < m + 1; i++) { // N
        cin >> x[i];
        cin >> y[i];
        pointToValue[make_pair(x[i], y[i])] = i; // log(N)
    }

    for (int i = 1; i < m + 1; i++) {
        if (checkValid(i)) { // log(N)
            removablePoints.insert(i); // log(N)
        }
    }

    // start the game
    int i = 1;
    while (removablePoints.size()) { // N
        long temp;
        if (i % 2 == 1) {
            // choose max
            temp = *(removablePoints.rbegin()); // log(N)
        } else {
            // choose min
            temp = *(removablePoints.begin()); // log(N)
        }

        removablePoints.erase(temp);
        if (!checkValid(temp))
            continue;
        i++;

        // update data structure
        addResult(m + 1 - i, m, temp - 1);

        // update
        mark[temp] = true;
        updateSet(temp); // log(N)
    }

    // counting the result
    cout << result << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define vi vector <int>
#define all(v) v.begin(), v.end()
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
#define forn(i, from, n) for (int i = (int)(from); i < (int)(n); ++i)

const int INF = 1e9 + 9;

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

#ifdef LOCAL
	freopen("in", "r", stdin);
	freopen("out", "w", stdout);
#endif

    int n;
    cin >> n;
    vector <string> s(n);
    forn(i, 0, n)
        cin >> s[i];
    vector <pii> ch(n);
    vi best(n, 0);
    vector <bool> is(n, 0);
    forn(i, 0, n){
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][j] != s[i][0]){
                ch[i].first = j;
                break;
            }
        }
        for (int j = s[i].size() - 1; j >= -1; --j){
            if (j < 0 || s[i][j] != s[i].back()){
                ch[i].second = s[i].size() - j - 1;
                break;
            }
        }
        int last = 0;
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][last] != s[i][j]){
                best[i] = max(best[i], j - last);
                last = j;
            }
        }
        is[i] = (best[i] == s[i].size());
    }
    vi dp(n, 0);
    vector <pii> cdp(n), sym(n);
    dp[n - 1] = best[n - 1];
    cdp[n - 1] = ch[n - 1];
    sym[n - 1] = {s[n - 1][0], s[n - 1].back()};
    for (int i = n - 2; i >= 0; --i){
        dp[i] = dp[i + 1];
        int cur = 0;
        cdp[i] = cdp[i + 1];
        bool going = 1;
        forn(j, 0, s[i].size()){
            if (is[i + 1] && s[i][j] == sym[i + 1].second){
                cur += dp[i + 1] + 1;
                if (cur + dp[i + 1] > dp[i])
                    dp[i] = cur + dp[i + 1];
                if (going)
                    cdp[i].first = cur + dp[i + 1];
            }
            else{
                going = 0;
                cur = 1;
                if (sym[i + 1].second == s[i][j])
                    cur += cdp[i + 1].second;
                if (sym[i + 1].first == s[i][j])
                    cur += cdp[i + 1].first;
                if (cur > dp[i])
                    dp[i] = cur;
                cur = 0;
            }
        }
        for (int j = s[i].size() - 1; j >= 0; --j){
            if (is[i + 1] && s[i][j] == sym[i + 1].second)
                cdp[i].second = (s[i].size() - 1 - j + 2) * dp[i + 1] + (s[i].size() - 1 - j + 1);
        }
        is[i] = (dp[i] == (s[i].size() + 1) * dp[i + 1] + s[i].size());
        sym[i] = sym[i + 1];
    }
    cout << dp[0];
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define vi vector <int>
#define all(v) v.begin(), v.end()
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
#define forn(i, from, n) for (int i = (int)(from); i < (int)(n); ++i)

const int INF = 1e9 + 9;

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

#ifdef LOCAL
	freopen("in", "r", stdin);
	freopen("out", "w", stdout);
#endif

    int n;
    cin >> n;
    vector <string> s(n);
    forn(i, 0, n)
        cin >> s[i];
    vector <pii> ch(n);
    vi best(n, 0);
    vector <bool> is(n, 0);
    forn(i, 0, n){
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][j] != s[i][0]){
                ch[i].first = j;
                break;
            }
        }
        for (int j = s[i].size() - 1; j >= -1; --j){
            if (j < 0 || s[i][j] != s[i].back()){
                ch[i].second = s[i].size() - j - 1;
                break;
            }
        }
        int last = 0;
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][last] != s[i][j]){
                best[i] = max(best[i], j - last);
                last = j;
            }
        }
        is[i] = (best[i] == s[i].size());
    }
    vi dp(n, 0);
    vector <pii> cdp(n), sym(n);
    dp[n - 1] = best[n - 1];
    cdp[n - 1] = ch[n - 1];
    sym[n - 1] = {s[n - 1][0], s[n - 1].back()};
    for (int i = n - 2; i >= 0; --i){
        dp[i] = dp[i + 1];
        int cur = 1;
        cdp[i] = cdp[i + 1];
        bool going = 1;
        forn(j, 0, s[i].size()){
            if (is[i + 1] && s[i][j] == sym[i + 1].second){
                cur += dp[i + 1];
                if (cur > dp[i])
                    dp[i] = cur;
                if (going)
                    cdp[i].first = cur;
            }
            else{
                going = 0;
                cur = 1;
                if (sym[i + 1].second == s[i][j])
                    cur += cdp[i + 1].second;
                if (cur > dp[i])
                    dp[i] = cur;
            }
        }
        if (going)
            cdp[i].first = s[i].size() + dp[i + 1];
        for (int j = s[i].size() - 1; j >= 0; --j){
            if (is[i + 1] && s[i][j] == sym[i + 1].second)
                cdp[i].second = (s[i].size() - 1 - j + 2) * dp[i + 1] + (s[i].size() - 1 - j + 1);
        }
        if (s[i].back() == sym[i + 1].first){
            cur += cdp[i + 1].first;
            if (cur > dp[i])
                dp[i] = cur;
        }
        is[i] = (dp[i] == s[i].size() + dp[i + 1]);
        sym[i] = sym[i + 1];
    }
    cout << dp[0];
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define vi vector <int>
#define all(v) v.begin(), v.end()
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
#define forn(i, from, n) for (int i = (int)(from); i < (int)(n); ++i)

const int INF = 1e9 + 9;

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

#ifdef LOCAL
	freopen("in", "r", stdin);
	freopen("out", "w", stdout);
#endif

    int n;
    cin >> n;
    vector <string> s(n);
    forn(i, 0, n)
        cin >> s[i];
    vector <pii> ch(n);
    vi best(n, 0);
    vector <bool> is(n, 0);
    forn(i, 0, n){
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][j] != s[i][0]){
                ch[i].first = j;
                break;
            }
        }
        for (int j = s[i].size() - 1; j >= -1; --j){
            if (j < 0 || s[i][j] != s[i].back()){
                ch[i].second = s[i].size() - j - 1;
                break;
            }
        }
        int last = 0;
        forn(j, 0, s[i].size() + 1){
            if (j >= s[i].size() || s[i][last] != s[i][j]){
                best[i] = max(best[i], j - last);
                last = j;
            }
        }
        is[i] = (best[i] == s[i].size());
    }
    vi dp(n, 0);
    vector <pii> cdp(n), sym(n);
    dp[n - 1] = best[n - 1];
    cdp[n - 1] = ch[n - 1];
    sym[n - 1] = {s[n - 1][0], s[n - 1].back()};
    for (int i = n - 2; i >= 0; --i){
        dp[i] = dp[i + 1];
        int cur = cdp[i + 1].second;
        cdp[i] = cdp[i + 1];
        bool going = 1;
        forn(j, 0, s[i].size()){
            if (is[i + 1] && s[i][j] == sym[i + 1].second){
                cur += dp[i + 1];
                if (cur > dp[i])
                    dp[i] = cur;
                if (going)
                    cdp[i].first = cur;
            }
            else{
                going = 0;
                cur = 1;
                if (sym[i + 1].second == s[i][j])
                    cur += cdp[i + 1].second;
                if (cur > dp[i])
                    dp[i] = cur;
            }
        }
        if (going)
            cdp[i].first = s[i].size() + dp[i + 1];
        for (int j = s[i].size() - 1; j >= 0; --j){
            if (is[i + 1] && s[i][j] == sym[i + 1].second)
                cdp[i].second = (s[i].size() - 1 - j + 2) * dp[i + 1] + (s[i].size() - 1 - j + 1);
        }
        if (s[i].back() == sym[i + 1].first){
            cur += cdp[i + 1].first;
            if (cur > dp[i])
                dp[i] = cur;
        }
        is[i] = (dp[i] == s[i].size() + dp[i + 1]);
        sym[i] = sym[i + 1];
    }
    cout << dp[0];
	return 0;
}


// 2020.11.28
// Code by LTb
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
#define debug puts("QwQ");
inline int read(){
    int x=0,f=1;
    char ch;
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

inline char readch(){
	char ch=getchar();
	while (ch==' '||ch=='\n') ch=getchar();
	return ch;
}

inline string readstr(){
	char ch=getchar();
	string ans="";
	while (ch==' '||ch=='\n') ch=getchar();
	while (ch!=' '&&ch!='\n') {ans+=ch;ch=getchar();}
	return ans;
}
inline void chmax(int &x,int y) {x=max(x,y);}

const int MAXN=100005;
int n;
string a[MAXN];
int siz[MAXN];
int youl[MAXN][30][2];
int dp[MAXN][30];
int ans=1;

signed main()

{
	n=read();
	for (int i=1;i<=n;i++){
		a[i]="N"+readstr();
		siz[i]=a[i].size()-1;
	}

	for (int j=1;j<=n;j++){
		for (int i=1;i<=26;i++){
			char now=i+'a'-1;
			while (youl[j][i][0]<siz[j] && a[j][youl[j][i][0]+1]==now) youl[j][i][0]++;
			while (youl[j][i][1]<siz[j] && a[j][siz[j]-youl[j][i][1]]==now) youl[j][i][1]++;
		}
	}

	for (int i=1;i<=siz[1];i++){
		int cur=i;
		while (cur<siz[1] && a[1][cur+1]==a[1][cur]) cur++;
		chmax(dp[1][a[1][i]-'a'+1],cur-i+1);
		i=cur;
	}

	for (int i=2;i<=n;i++){
		for (int j=1;j<=siz[1];j++){
			int cur=j;
			while (cur<siz[i] && a[i][cur+1]==a[i][cur]) cur++;
			chmax(dp[i][a[i][j]-'a'+1],cur-j+1);
			j=cur;
		}

		for (int j=1;j<=26;j++){
			chmax(dp[i][j],max(youl[i][j][0],youl[i][j][1]));
			if (dp[i-1][j]){
				chmax(dp[i][j],1+youl[i][j][1]+youl[i][j][0]);
				if (youl[i][j][0]==siz[i])
					chmax(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*siz[i]);
			}
			// chmax(ans,dp[i][j]);
		}
	}

	for (int i=1;i<=26;i++)
		chmax(ans,dp[n][i]);

	cout<<ans<<endl;
	return 0;
}


// 2020.11.28
// Code by LTb
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
#define debug puts("QwQ");
inline int read(){
    int x=0,f=1;
    char ch;
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

inline char readch(){
	char ch=getchar();
	while (ch==' '||ch=='\n') ch=getchar();
	return ch;
}

inline string readstr(){
	char ch=getchar();
	string ans="";
	while (ch==' '||ch=='\n') ch=getchar();
	while (ch!=' '&&ch!='\n') {ans+=ch;ch=getchar();}
	return ans;
}
inline void chmax(int &x,int y) {x=max(x,y);}

const int MAXN=100005;
int n;
string a[MAXN];
int siz[MAXN];
int youl[MAXN][30][2];
int dp[MAXN][30];
int ans=1;

signed main()

{
	n=read();
	for (int i=1;i<=n;i++){
		a[i]="N"+readstr();
		siz[i]=a[i].size()-1;
	}

	for (int j=1;j<=n;j++){
		for (int i=1;i<=26;i++){
			char now=i+'a'-1;
			while (youl[j][i][0]<siz[j] && a[j][youl[j][i][0]+1]==now) youl[j][i][0]++;
			while (youl[j][i][1]<siz[j] && a[j][siz[j]-youl[j][i][1]]==now) youl[j][i][1]++;
		}
	}

	for (int i=1;i<=siz[1];i++){
		int cur=i;
		while (cur<siz[1] && a[1][cur+1]==a[1][cur]) cur++;
		chmax(dp[1][a[1][i]-'a'+1],cur-i+1);
		i=cur;
	}

	for (int i=2;i<=n;i++){
		for (int j=1;j<=siz[i];j++){
			int cur=j;
			while (cur<siz[i] && a[i][cur+1]==a[i][cur]) cur++;
			chmax(dp[i][a[i][j]-'a'+1],cur-j+1);
			j=cur;
		}

		for (int j=1;j<=26;j++){
			chmax(dp[i][j],max(youl[i][j][0],youl[i][j][1]));
			if (dp[i-1][j]){
				chmax(dp[i][j],1+youl[i][j][1]+youl[i][j][0]);
				if (youl[i][j][0]==siz[i])
					chmax(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*siz[i]);
			}
			// chmax(ans,dp[i][j]);
		}
	}

	for (int i=1;i<=26;i++)
		chmax(ans,dp[n][i]);

	cout<<ans<<endl;
	return 0;
}


// 2020.11.28
// Code by LTb
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
#define debug puts("QwQ");
inline int read(){
    int x=0,f=1;
    char ch;
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

inline char readch(){
	char ch=getchar();
	while (ch==' '||ch=='\n') ch=getchar();
	return ch;
}

inline string readstr(){
	char ch=getchar();
	string ans="";
	while (ch==' '||ch=='\n') ch=getchar();
	while (ch!=' '&&ch!='\n') {ans+=ch;ch=getchar();}
	return ans;
}
inline void chmax(int &x,int y) {x=max(x,y);}

const int MAXN=100005;
int n;
string a[MAXN];
int siz[MAXN];
int youl[MAXN][30][2];
int dp[MAXN][30];
int ans=1;

signed main()

{
	n=read();
	for (int i=1;i<=n;i++){
		a[i]="N"+readstr();
		siz[i]=a[i].size()-1;
	}

	for (int j=1;j<=n;j++){
		for (int i=1;i<=26;i++){
			char now=i+'a'-1;
			while (youl[j][i][0]<siz[j] && a[j][youl[j][i][0]+1]==now) youl[j][i][0]++;
			while (youl[j][i][1]<siz[j] && a[j][siz[j]-youl[j][i][1]]==now) youl[j][i][1]++;
		}
	}

	for (int i=1;i<=siz[1];i++){
		int cur=i;
		while (cur<siz[1] && a[1][cur+1]==a[1][cur]) cur++;
		chmax(dp[1][a[1][i]-'a'+1],cur-i+1);
		i=cur;
	}

	for (int i=2;i<=n;i++){
		for (int j=1;j<=26;j++){
			chmax(dp[i][j],max(youl[i][j][0],youl[i][j][1]));
			if (dp[i-1][j]){
				chmax(dp[i][j],1+youl[i][j][1]+youl[i][j][0]);
				if (youl[i][j][0]==siz[i])
					chmax(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*siz[i]);
			}
			// chmax(ans,dp[i][j]);
		}
	}

	for (int i=1;i<=26;i++)
		chmax(ans,dp[n][i]);

	cout<<ans<<endl;
	return 0;
}


// 2020.11.28
// Code by LTb
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define debug puts("QwQ");
inline int read(){
    int x=0,f=1;
    char ch;
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

inline char readch(){
	char ch=getchar();
	while (ch==' '||ch=='\n') ch=getchar();
	return ch;
}

inline string readstr(){
	char ch=getchar();
	string ans="";
	while (ch==' '||ch=='\n') ch=getchar();
	while (ch!=' '&&ch!='\n') {ans+=ch;ch=getchar();}
	return ans;
}
inline void chmax(int &x,int y) {x=max(x,y);}

const int MAXN=100005;
int n;
string a[MAXN];
int siz[MAXN];
int youl[MAXN][30][2];
int dp[MAXN][30];
int ans=1;

signed main()

{
	n=read();
	for (int i=1;i<=n;i++){
		a[i]="N"+readstr();
		siz[i]=a[i].size()-1;
	}

	for (int j=1;j<=n;j++){
		for (int i=1;i<=26;i++){
			char now=i+'a'-1;
			while (youl[j][i][0]<siz[j] && a[j][youl[j][i][0]+1]==now) youl[j][i][0]++;
			while (youl[j][i][1]<siz[j] && a[j][siz[j]-youl[j][i][1]]==now) youl[j][i][1]++;
		}
	}

	for (int i=1;i<=siz[1];i++){
		int cur=i;
		while (cur<siz[1] && a[1][cur+1]==a[1][cur]) cur++;
		chmax(dp[1][a[1][i]-'a'+1],cur-i+1);
		i=cur;
	}

	for (int i=2;i<=n;i++){
		for (int j=1;j<=26;j++){
			chmax(dp[i][j],max(youl[i][j][0],youl[i][j][1]));
			if (dp[i-1][j]){
				chmax(dp[i][j],1+youl[i][j][1]+youl[i][j][0]);
				if (youl[i][j][0]==siz[i])
					chmax(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*siz[i]);
			}
			// chmax(ans,dp[i][j]);
		}
	}

	for (int i=1;i<=26;i++)
		chmax(ans,dp[n][i]);

	cout<<ans<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define fi first
#define se second
#define pi acos(-1.0)
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk mack_pair
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int inf = 0x3f3f3f3f;
const db eps = 1e-12;
const int N = 1e5 + 5;
const int mod = 998244353;
int n, m, ans;
int dp[N][30], cnt[30];
char s[N];

int main(){
    scanf("%d", &n);
    rep(i, 1, n){
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        int t1 = 1, t2 = 1, t = 1;
        mem(cnt, 0);
        rep(i, 2, n)
            if(s[i] == s[i-1]) t++;
            else cnt[s[i-1]-'a'] = max(cnt[s[i-1]-'a'], t), t = 1;
        cnt[s[n]-'a'] = max(cnt[s[n]-'a'], t);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t1++;
            else break;
        per(i, len-1, 1)
            if(s[i] == s[i+1]) t2++;
            else break;

        if(t1 == len)
            dp[i][s[1]-'a'] = (t1 + 1) * dp[i-1][s[1]-'a'] + t1;
        rep(j, 0, 25){
            dp[i][j] = max(dp[i][j], cnt[j]);
            if(!dp[i-1][j]) continue;
            dp[i][j] = max(dp[i][j], 1);
            if(s[1] == 'a' + j && s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + t2 + 1);
            else if(s[1] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + 1);
            else if(s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t2 + 1);
        }
    }
    rep(i, 0, 25) ans = max(ans, dp[n][i]);
    printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define fi first
#define se second
#define pi acos(-1.0)
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk mack_pair
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int inf = 0x3f3f3f3f;
const db eps = 1e-12;
const int N = 1e5 + 5;
const int mod = 998244353;
int n, m, ans;
int dp[N][30], cnt[30];
char s[N];

int main(){
    scanf("%d", &n);
    rep(i, 1, n){
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        int t1 = 1, t2 = 1, t = 1;
        mem(cnt, 0);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t++;
            else cnt[s[i-1]-'a'] = max(cnt[s[i-1]-'a'], t), t = 1;
        cnt[s[len]-'a'] = max(cnt[s[len]-'a'], t);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t1++;
            else break;
        per(i, len-1, 1)
            if(s[i] == s[i+1]) t2++;
            else break;

        if(t1 == len)
            dp[i][s[1]-'a'] = (t1 + 1) * dp[i-1][s[1]-'a'] + t1;
        rep(j, 0, 25){
            dp[i][j] = max(dp[i][j], cnt[j]);
            if(!dp[i-1][j]) continue;
            dp[i][j] = max(dp[i][j], 1);
            if(s[1] == 'a' + j && s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + t2 + 1);
            else if(s[1] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + 1);
            else if(s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t2 + 1);
            //printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
        }
    }
    rep(i, 0, 25) ans = max(ans, dp[n][i]);
    printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define fi first
#define se second
#define pi acos(-1.0)
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk mack_pair
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int inf = 0x3f3f3f3f;
const db eps = 1e-12;
const int N = 1e5 + 5;
const int mod = 998244353;
int n, m, ans;
int dp[N][30], cnt[30];
char s[N];

int main(){
    scanf("%d", &n);
    rep(i, 1, n){
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        int t1 = 1, t2 = 1, t = 1;
        mem(cnt, 0);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t++;
            else cnt[s[i-1]-'a'] = max(cnt[s[i-1]-'a'], t), t = 1;
        cnt[s[n]-'a'] = max(cnt[s[n]-'a'], t);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t1++;
            else break;
        per(i, len-1, 1)
            if(s[i] == s[i+1]) t2++;
            else break;

        if(t1 == len)
            dp[i][s[1]-'a'] = (t1 + 1) * dp[i-1][s[1]-'a'] + t1;
        rep(j, 0, 25){
            dp[i][j] = max(dp[i][j], cnt[j]);
            if(!dp[i-1][j]) continue;
            dp[i][j] = max(dp[i][j], 1);
            if(s[1] == 'a' + j && s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + t2 + 1);
            else if(s[1] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + 1);
            else if(s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t2 + 1);
        }
    }
    rep(i, 0, 25) ans = max(ans, dp[n][i]);
    printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define fi first
#define se second
#define pi acos(-1.0)
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk mack_pair
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int inf = 0x3f3f3f3f;
const db eps = 1e-12;
const int N = 1e5 + 5;
const int mod = 998244353;
int n, m, ans;
int dp[N][30], cnt[30];
char s[N];

int main(){
    scanf("%d", &n);
    rep(i, 1, n){
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        int t1 = 1, t2 = 1, t = 1;
        mem(cnt, 0);
        rep(i, 2, n)
            if(s[i] == s[i-1]) t++;
            else cnt[s[i-1]-'a'] = max(cnt[s[i-1]-'a'], t), t = 1;
        cnt[s[n]-'a'] = max(cnt[s[n]-'a'], t);
        rep(i, 2, len)
            if(s[i] == s[i-1]) t1++;
            else break;
        per(i, len-1, 1)
            if(s[i] == s[i+1]) t2++;
            else break;

        if(t1 == len)
            dp[i][s[1]-'a'] = (t1 + 1) * dp[i-1][s[1]-'a'] + t1;
        rep(j, 0, 25){
            dp[i][j] = max(dp[i][j], cnt[j]);
            if(dp[i-1][j]){
                dp[i][j] = max(dp[i][j], 1);
                if(s[1] == 'a' + j && s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + t2 + 1);
                else if(s[1] == 'a' + j) dp[i][j] = max(dp[i][j], t1 + 1);
                else if(s[len] == 'a' + j) dp[i][j] = max(dp[i][j], t2 + 1);
            }
            ans = max(ans, dp[i][j]);
        }
    }
    printf("%d\n", ans);
    return 0;
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));
  int tot = sz(s[n-1]);
  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int biggest=0;
    for(int j=0;j<sz(s[i]);){
      if(s[i][j]!=c){
        j++;
        continue;
      }

      int ini =j;

      while(j<sz(s[i]) and s[i][j]==c){
        j++;
      }
      biggest = max(biggest,j-ini);
    }
    int tam = best;

    if(biggest > 0){
      best = max(best , Suf + 1 + Pre);
    }

    if(justone){
      int t1 = (spre + 1)*tot + spre;
      int t2 = (ssuf + 1)*tot + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }

    if(justone){
      best = max(best,(biggest + 1) * tam + biggest);
    }

    if(spre!=sz(s[i]))justone=0,tot=0;
    else if(justone){
      tot = tot*(sz(s[i]) + 1) + sz(s[i]);
    }
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));
  int tot = sz(s[n-1]);
  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int biggest=0;
    for(int j=0;j<sz(s[i]);){
      if(s[i][j]!=c){
        j++;
        continue;
      }

      int ini =j;

      while(j<sz(s[i]) and s[i][j]==c){
        j++;
      }
      biggest = max(biggest,j-ini);
    }
    int tam = best;

    if(biggest > 0){
      best = max(best , Suf + 1 + Pre);
    }

    if(justone){
      int t1 = (spre + 1)*tot + spre;
      int t2 = (ssuf + 1)*tot + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }

    if(justone){
      best = max(best,(biggest + 1) * tam + biggest);
    }

    if(spre!=sz(s[i]))justone=0;
    else{
      tot = tot*(sz(s[i]) + 1) + sz(s[i]);
    }
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));

  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int biggest=0;
    for(int j=0;j<sz(s[i]);){
      int ini =j;
      if(s[i][j]!=c){
        j++;
        continue;
      }
      while(j<sz(s[i]) and s[i][j]==c){
        j++;
      }
      biggest = max(biggest,j-ini);
    }
    int tam = best;
    if(justone){
      int t1 = (spre + 1)*best + spre;
      int t2 = (ssuf + 1)*best + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }else if(biggest>0){
      best = max(best,Suf + 1 + Pre);
    }

    if(justone){
      best = max(best,(biggest + 1) * tam + biggest);
    }

    if(spre!=sz(s[i]))justone=0;
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int pre=0;
  int suf=0;
  while(pre < s[n-1].size() and s[n-1][pre]==c)pre++;
  while(suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - suf]==c)suf++;

  if(pre==sz(s[n-1]))justone = 1;
  best = max(best,max(pre,suf));

  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;
    int cur = min(spre,ssuf);

    if(justone){
      int t1 = (spre + 1)*best + spre;
      int t2 = (ssuf + 1)*best + ssuf;
      pre = t1,suf = t2;
      best = max(best,max(t1,t2));
    }else if(spre or ssuf){
      best = max(best,suf + 1 + pre);
      best = max(best,suf + 1 + pre);
    }

    if(spre!=sz(s[i]))justone=0;
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  for(int j=0;j<sz(s[n-1]);){
    if(s[n-1][j]!=c){
      j++;
      continue;
    }
    int ini = j;
    while(j < sz(s[n-1]) and s[n-1][j]==c){
      j++;
    }
    best= max(best,j-ini);
  }

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));
  int tot = sz(s[n-1]);
  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int biggest=0;
    for(int j=0;j<sz(s[i]);){
      if(s[i][j]!=c){
        j++;
        continue;
      }

      int ini =j;

      while(j<sz(s[i]) and s[i][j]==c){
        j++;
      }
      biggest = max(biggest,j-ini);
    }
    int tam = best;

    if(biggest > 0){
      best = max(best , Suf + 1 + Pre);
    }

    if(justone){
      int t1 = (spre + 1)*tot + spre;
      int t2 = (ssuf + 1)*tot + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }

    if(justone){
      best = max(best,(biggest + 1) * tam + biggest);
    }

    if(spre!=sz(s[i]))justone=0,tot=0;
    else if(justone){
      tot = tot*(sz(s[i]) + 1) + sz(s[i]);
    }
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));

  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int someone =0;
    for(int j=0;j<sz(s[i]);j++){
      if(s[i][j]==c)someone = 1;
    }

    if(justone){
      int t1 = (spre + 1)*best + spre;
      int t2 = (ssuf + 1)*best + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }else if(someone){
      best = max(best,Suf + 1 + Pre);
    }

    if(spre!=sz(s[i]))justone=0;
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int pre=0;
  int suf=0;
  while(pre < s[n-1].size() and s[n-1][pre]==c)pre++;
  while(suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - suf]==c)suf++;

  if(pre==sz(s[n-1]))justone = 1;
  best = max(best,max(pre,suf));
  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-suf]==c)ssuf++;
    int cur = min(spre,ssuf);

    if(justone){
      int t1 = (spre + 1)*best + spre;
      int t2 = (ssuf + 1)*best + ssuf;
      pre = t1,suf = t2;
      best = max(best,max(t1,t2));
    }else if(spre or ssuf){
      best = max(best,suf + 1 + pre);
      best = max(best,suf + 1 + pre);
    }

    if(spre!=sz(s[i]))justone=0;
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#define ld long double
#define endl "\n"
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define ms(v,x) memset(v,x,sizeof(v))
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
//#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define td(v) v.begin(),v.end()
#define sz(v) (int)v.size()
//#define M   1000000007 // 1e9 + 7
#define int long long
using namespace std;
typedef vector<int> vi;
#define y1 abacaba
typedef long long ll;
typedef pair<int,int> pii;
inline ll mod(ll n, ll m ){ ll ret = n%m; if(ret < 0) ret += m; return ret; }
ll gcd(ll a, ll b){return (b == 0LL ? a : gcd(b, a%b));}
ll exp(ll a,ll b,ll m){
    if(b==0LL) return 1LL;
    if(b==1LL) return mod(a,m);
    ll k = mod(exp(a,b/2,m),m);
    if(b&1LL){
        return mod(a*mod(k*k,m),m);
    }
    else return mod(k*k,m);
}

const int N = 100100;
string s[N];

  int n;
int solve(char c){
  int best = 0;

  int justone=0;

  int Pre=0;
  int Suf=0;
  while(Pre < s[n-1].size() and s[n-1][Pre]==c)Pre++;
  while(Suf < s[n-1].size() and s[n-1][sz(s[n-1]) - 1 - Suf]==c)Suf++;

  if(Pre==sz(s[n-1]))justone = 1;
  best = max(best,max(Pre,Suf));
  int tot = sz(s[n-1]);
  for(int i=n-2;i>=0;i--){

    int spre=0,ssuf=0;
    while(spre<sz(s[i]) and s[i][spre]==c)spre++;
    while(ssuf<sz(s[i]) and s[i][sz(s[i])-1-ssuf]==c)ssuf++;

    int biggest=0;
    for(int j=0;j<sz(s[i]);){
      if(s[i][j]!=c){
        j++;
        continue;
      }

      int ini =j;

      while(j<sz(s[i]) and s[i][j]==c){
        j++;
      }
      biggest = max(biggest,j-ini);
    }
    int tam = best;
    if(justone){
      int t1 = (spre + 1)*tot + spre;
      int t2 = (ssuf + 1)*tot + ssuf;
      Pre = t1,Suf = t2;
      best = max(best,max(t1,t2));
    }

    if(biggest > 0){
      best = max(best , Suf + 1 + Pre);
    }

    if(justone){
      best = max(best,(biggest + 1) * tam + biggest);
    }

    if(spre!=sz(s[i]))justone=0;
    else{
      tot = tot*(sz(s[i]) + 1) + sz(s[i]);
    }
  }

  return best;
}

int32_t main(){
  fastio;

  cin>>n;
  for(int i=0;i<n;i++){
    cin >> s[i];
  }

  int ans = 1;
  for(int i=0;i<26;i++){
    ans = max(ans , solve('a' + i));
  }
  cout << ans << endl;
  // Math -> gcd it all
  // Did u check N=1? Did you switch N,M?
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 1
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005
#define e9 1000000000

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());
	else {
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['a'])
		tr(ans['b'])
		tr(ans['c'])
		tr(ans['d'])
		tr(ans['e'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					tr(mx)
					cur_pre = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
					ans[cur_pre.fi] = min(ans[cur_pre.fi], e9);
 				}
				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
					ans[cur_suf.fi] = min(ans[cur_suf.fi], e9);
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * cur_sg.se + len[i][c]);
					ans[c] = min(ans[c], e9);
				}
				cur_pre = cur_suf = mp(cur_sg.fi, cur_sg.se);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
				ans[c] = min(ans[c], e9);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());
	else {
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['v'])
		tr(ans['r'])
		tr(ans['h'])
		tr(ans['p'])
		tr(ans['l'])
		tr(ans['b'])
		tr(ans['n'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					cur_pre = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
				}
				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * ans[c] + len[i][c]);
				}
				cur_pre = cur_suf = mp(cur_sg.fi, cur_sg.se);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());

	// initial pre/suf
	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['a'])
		tr(ans['b'])
		tr(ans['c'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					cur_pre = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
				}
				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * ans[c] + len[i][c]);
				}
				cur_pre = cur_suf = mp(cur_sg.fi, cur_sg.se);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005
#define e9 1000000000

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());
	else {
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['a'])
		tr(ans['b'])
		tr(ans['c'])
		tr(ans['d'])
		tr(ans['e'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					tr(mx)
					cur_pre = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
					ans[cur_pre.fi] = min(ans[cur_pre.fi], e9);
 				}
 				else {
 					cur_pre = cur_sg;
				}

				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
					ans[cur_suf.fi] = min(ans[cur_suf.fi], e9);
				}
				else {
					cur_suf = cur_sg;
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * cur_sg.se + len[i][c]);
					ans[c] = min(ans[c], e9);
				}
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
				ans[c] = min(ans[c], e9);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005
#define e9 1000000000

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());
	else {
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['v'])
		tr(ans['r'])
		tr(ans['h'])
		tr(ans['p'])
		tr(ans['l'])
		tr(ans['b'])
		tr(ans['n'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					tr(mx)
					cur_pre = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
					ans[cur_pre.fi] = min(ans[cur_pre.fi], e9);
 				}
				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, ans[cur_sg.fi] * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
					ans[cur_suf.fi] = min(ans[cur_suf.fi], e9);
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * cur_sg.se + len[i][c]);
					ans[c] = min(ans[c], e9);
				}
				cur_pre = cur_suf = mp(cur_sg.fi, cur_sg.se);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
				ans[c] = min(ans[c], e9);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005
#define e9 1000000000

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];
	cerr << id << ' ' << s << '\n';

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, s.length())));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());

	else {
		test
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	tr(a[1])

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['a'])
		tr(ans['b'])
		tr(ans['c'])
		tr(ans['d'])
		tr(ans['e'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					cur_pre = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
					ans[cur_pre.fi] = min(ans[cur_pre.fi], e9);
 				}
 				else {
 					cur_pre = cur_sg;
				}

				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
					ans[cur_suf.fi] = min(ans[cur_suf.fi], e9);
				}
				else {
					cur_suf = cur_sg;
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * cur_sg.se + len[i][c]);
					ans[c] = min(ans[c], e9);
				}
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
				ans[c] = min(ans[c], e9);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL
#define MAXN 100005
#define e9 1000000000

int n, ans[256], len[MAXN][256];
string a[MAXN];
pair<char, int> cur_pre, cur_suf, cur_sg;

void genans(int id) {
	vector<pair<char, pii> > v;
	string &s = a[id];

	v.pb(mp(s[0], mp(0, s.length())));

	for (int i = 1; i < s.length(); i++) {
		if (s[i] != s[i - 1]) v.back().se.se = i, v.pb(mp(s[i], mp(i, n)));
	}

	for (auto x : v) len[id][x.fi] = max(len[id][x.fi], x.se.se - x.se.fi);
}

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

	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	reverse(a + 1, a + 1 + n);

	for (int i = 1; i <= n; i++) genans(i);

	for (char c = 'a'; c <= 'z'; c++) ans[c] = len[1][c];

	if ((*max_element(ans + 'a', ans + 'z' + 1)) == a[1].length())
		cur_sg = mp((max_element(ans + 'a', ans + 'z' + 1)) - ans, a[1].length());
	else {
		int mx;
		for (int pos = 0; pos < a[1].length(); pos++) {
			if (a[1][pos] != a[1][0]) {
				mx = pos;
				break;
			}
		}
		cur_pre = mp(a[1][0], mx);

		for (int pos = a[1].length() - 1; pos >= 0; pos--) {
			if (a[1][pos] != a[1].back()) {
				mx = a[1].length() - 1 - pos;
				break;
			}
		}
		cur_suf = mp(a[1].back(), mx);
	}

	cerr << "cur_sg " << cur_sg.fi << ' ' << cur_sg.se << '\n';

	for (int i = 2; i <= n; i++) {
		tr(ans['a'])
		tr(ans['b'])
		tr(ans['c'])
		tr(ans['d'])
		tr(ans['e'])
		cerr << "cur_pre " << cur_pre.fi << ' ' << cur_pre.se << '\n';
		cerr << "cur_suf " << cur_suf.fi << ' ' << cur_suf.se << '\n';

		if (cur_sg != mp((char)0, 0)) { // singular
			// maintain prefix, suffix
			if (len[i][a[i][0]] == a[i].length() && a[i][0] == cur_sg.fi) { // also a singular segment here!
				cur_sg = mp(cur_sg.fi, cur_sg.se * (len[i][a[i][0]] + 1) + len[i][a[i][0]]);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
			}
			else {
				if (a[i][0] == cur_sg.fi) {
					int mx;
					for (int pos = 0; pos < a[i].length(); pos++) {
						if (a[i][pos] != cur_sg.fi) {
							mx = pos;
							break;
						}
					}
					tr(mx)
					cur_pre = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_pre.fi] = max(ans[cur_pre.fi], cur_pre.se);
					ans[cur_pre.fi] = min(ans[cur_pre.fi], e9);
 				}
				if (a[i].back() == cur_sg.fi) {
					int mx;
					for (int pos = a[i].length() - 1; pos >= 0; pos--) {
						if (a[i][pos] != cur_sg.fi) {
							mx = a[i].length() - 1 - pos;
							break;
						}
					}
					cur_suf = mp(cur_sg.fi, cur_sg.se * (mx + 1) + mx);
					ans[cur_suf.fi] = max(ans[cur_suf.fi], cur_suf.se);
					ans[cur_suf.fi] = min(ans[cur_suf.fi], e9);
				}

				for (char c : a[i]) {
					// join multiple segments
					if (c == cur_sg.fi) ans[c] = max(ans[c], (len[i][c] + 1) * cur_sg.se + len[i][c]);
					ans[c] = min(ans[c], e9);
				}
				cur_pre = cur_suf = mp(cur_sg.fi, cur_sg.se);
				ans[cur_sg.fi] = max(ans[cur_sg.fi], cur_sg.se);
				ans[cur_sg.fi] = min(ans[cur_sg.fi], e9);
				cur_sg = mp(0, 0);
			}
		}
		else {
			for (char c : a[i]) {
				ans[c] = max(ans[c], 1 + (cur_pre.fi == c) * cur_pre.se + (cur_suf.fi == c) * cur_suf.se);
				ans[c] = min(ans[c], e9);
			}
		}
	}

	cout << (*max_element(ans + 'a', ans + 'z' + 1)) << '\n';
}