1.不能以某些位置结尾=不能以某些位置开头,于是倒转字符串
2.不考虑禁止的情况,则题目转化为height数组上求最大矩形,进行两次单调栈即可
3.考虑禁止的情况,实际上就等于计算次数的时候,减少合法区间内的1的个数
嗯,顺便存一下最终的fastio和后缀数组板子,以后应该不会再换了
#include<bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
using namespace std;//head
const int maxn=4e5+10,maxm=2e6+10;
const ll INF=0x3f3f3f3f,mod=1e9+7;
int casn,n,m,k,num[maxn];
namespace fastio{//@精简版,支持读取整数,字符串,输出整数@
bool isdecimal(char c){return (c >= 48 && c <= 57) || (c == 46);}
bool isdigit(char c){return c >= 48 && c <= 57;}
const int maxsz=10000000;
class fast_iostream{public:
bool endf = 1,flag;
char ch = get_char();
char get_char(){
static char buffer[maxsz], *a = buffer, *b = buffer;
return a == b && (b = (a = buffer) + fread(buffer, 1, maxsz, stdin), b == a) ? EOF : *a++;
}
template <typename type> bool get_signed(type& tmp){
flag = 0;tmp = 0;
while (!isdigit(ch) && ch != EOF){flag = ch == '-';ch = get_char();};
if (ch == EOF) return endf = 0;
do{tmp = tmp*10 + ch - 48;} while (isdigit(ch = get_char()));
if (flag) tmp = -tmp;
return 1;
}
template <typename type>bool get_unsigned(type& tmp){
tmp = 0;
while (!isdigit(ch) && ch != EOF) ch = get_char();
if (ch == EOF) return endf = 0;
do{tmp = tmp*10 + ch - 48;} while (isdigit(ch = get_char()));
return 1;
}
int get_str(char* str){
char* tmp = str;
while (ch == '
' || ch == '
' || ch == ' ') ch = get_char();
if (ch == EOF) return (endf = 0), *tmp = 0;
do{*(tmp++) = ch;ch = get_char();} while (ch != '
' && ch != '
' && ch != ' ' && ch != EOF);
*(tmp++) = ' ';
return static_cast<int>(tmp - str - 1);
}
typedef char* charptr;
fast_iostream& operator>>(char* tmp){get_str(tmp);return *this;}
template <typename type>fast_iostream& operator>>(type& tmp){get_signed(tmp);return *this;}
operator bool() const {return endf;}
};
template <typename type>void put(type tmp){
if (tmp == 0){putchar(48);return;}
static int top,stk[21];
if (tmp < 0){tmp = -tmp;putchar('-');}
while (tmp) stk[++top] = tmp % 10, tmp /= 10;
while (top) putchar(stk[top--] + 48);
}
}fastio::fast_iostream io;
#define rank _rank
namespace suffix{
int tr[maxn],rank[maxn],sa[maxn],h[maxn],has[maxn];
int cmp(int x,int y,int k){
if(x+k>n||y+k>n)return 0;
return rank[x]==rank[y]&&rank[x+k]==rank[y+k];
}
void getsa(char *s,int n,int m=233){
int i,cnt;
for(i=1;i<=n;i++)has[s[i]]++;
for(i=1,cnt=0;i<=m;i++)if(has[i])tr[i]=++cnt;
for(i=1;i<=m;i++)has[i]+=has[i-1];
for(i=1;i<=n;i++)rank[i]=tr[s[i]],sa[has[s[i]]--]=i;
for(int k=1;cnt!=n;k<<=1){
for(i=1;i<=n;i++)has[i]=0;
for(i=1;i<=n;i++)has[rank[i]]++;
for(i=1;i<=n;i++)has[i]+=has[i-1];
for(i=n;i>=1;i--)if(sa[i]>k)tr[sa[i]-k]=has[rank[sa[i]-k]]--;
for(i=1;i<=k;i++)tr[n-i+1]=has[rank[n-i+1]]--;
for(i=1;i<=n;i++)sa[tr[i]]=i;
for(i=1,cnt=0;i<=n;i++)tr[sa[i]]=cmp(sa[i],sa[i-1],k) ? cnt:++cnt;
for(i=1;i<=n;i++)rank[i]=tr[i];
}
for(int i=1;i<=n;i++){
if(rank[i]==1)continue;
for(int j=max(1,h[rank[i-1]]-1);;j++){
if(s[i+j-1]==s[sa[rank[i]-1]+j-1])h[rank[i]]=j;
else break;
}
}
}
}using namespace suffix;
char s1[maxn],s2[maxn];
int sum[maxn],l[maxn],r[maxn];
void getmn(int *a,int s,int t){
stack<int> stk;
while(!stk.empty()) stk.pop();
rep(i,s,t){
while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
if(!stk.empty()) l[i]=stk.top()+1;
else l[i]=s;
stk.push(i);
}
while(!stk.empty()) stk.pop();
per(i,s,t){
while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
if(!stk.empty()) r[i]=stk.top()-1;
else r[i]=t;
stk.push(i);
}
}
int main(){
io>>n;
io>>(s1+1)>>(s2+1);
reverse(s1+1,s1+1+n);
reverse(s2+1,s2+1+n);
getsa(s1,n,233);
rep(i,1,n) sum[i]=sum[i-1]+(s2[sa[i]]=='1');
ll ans=0;
rep(i,1,n) if(s2[i]=='0')ans=max(ans,n-i+1ll);
getmn(h,1,n);
rep(i,2,n) {
ll len=h[i],rg=(r[i]-l[i]+2-(sum[r[i]]-sum[max(0,l[i]-2)]));
ans=max(ans,len*rg);
}
fastio::put(ans);
}