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); }