You are given a string s consisting of n lowercase Latin letters. Some indices in this string are marked as forbidden.
You want to find a string a such that the value of |a|·f(a) is maximum possible, where f(a) is the number of occurences of a in s such that these occurences end in non-forbidden indices. So, for example, if s is aaaa, a is aa and index 3 is forbidden, then f(a) = 2 because there are three occurences of a in s (starting in indices 1, 2 and 3), but one of them (starting in index 2) ends in a forbidden index.
Calculate the maximum possible value of |a|·f(a) you can get.
The first line contains an integer number n (1 ≤ n ≤ 200000) — the length of s.
The second line contains a string s, consisting of n lowercase Latin letters.
The third line contains a string t, consisting of n characters 0 and 1. If i-th character in t is 1, then i is a forbidden index (otherwise i is not forbidden).
Print the maximum possible value of |a|·f(a).
5 ababa 00100
5
5 ababa 00000
6
5 ababa 11111
0
题解:
某些位置不可以作为串的结束位置,这样不好做,把这个字符串反序。然后限制条件就变成了有的字符不能作为串的开始。
然后对字符串求后缀数组sa和高度数组height。
然后的话,求|a|*f(a)的值就对应到了height数组里面的最大矩形面积,用单调栈的方法进行处理,但是有限制条件,即矩形块中有的部分是以forbidden为开始的后缀,不能被算进去,所以还要减去这些被限制的后缀串。用前缀sum维护即可在O(1)的时间内减去限制串数目。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct P{
int i,w,forbid;
};
int n;
const int maxn = 200007;
int wa[maxn],wb[maxn],wv[maxn],cnt[maxn];
int cmp(int *r , int a, int b, int l,int n)
{
int a2 = a+l >= n ? -1:r[a+l];
int b2 = b+l >= n ? -1:r[b+l];
return r[a] == r[b] && a2 == b2;
}
void da (int *r , int *sa , int n, int m)
{
int i, j, p, *x = wa, *y = wb , *t;
for(i = 0; i < m; i++)
cnt[i] = 0;
for(i = 0; i < n; i++)
cnt[x[i] = r[i]]++;
for(i = 1; i < m; i++)
cnt[i] += cnt[i-1];
for(i = n-1; i >= 0; i--)
sa[--cnt[x[i]]] = i;
for(j = 1,p = 1; p < n ; j *= 2,m = p)
{
for(p = 0, i = n - j; i < n; i++)
y[p++]=i;
for(i = 0; i < n; i++)
if(sa[i] >= j)
y[p++] = sa[i] - j;
for(i = 0; i < n; i++)
wv[i] = x[y[i]];
for(i = 0; i < m; i++)
cnt[i] = 0;
for(i = 0; i < n; i++)
cnt[wv[i]]++;
for(i = 1; i < m; i++)
cnt[i] += cnt[i-1];
for(i = n-1; i >= 0; i--)
sa[--cnt[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1; i < n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j,n)?p-1:p++;
}
}
int height[maxn],rk[maxn];
void calcheight(int *r,int *sa,int n){
int i,j,k = 0;
for(int i = 0;i < n;i++) rk[sa[i]] = i;
for(i = 0;i < n;height[rk[i++]] = k)
for(k?k--:0,j = sa[rk[i]?rk[i]-1:0];rk[i]>0 &&i+k<n && j+k<n && r[i+k] == r[j+k];k++);
}
char s[maxn];
int per[maxn];
int sa[maxn];
int r[maxn];
P stk[maxn];
int top;
int sum[maxn];
main(){
cin>>n;
char c;
for(int i = 0;i < n;i++){
char c;
scanf(" %c",&c);
s[n-1-i] = c;
r[n-1-i] = c - 'a' + 1;
}
s[n] = 0;
int ans = 0;
for(int i = 0;i < n;++i){
char c;
scanf(" %c",&c);
per[n-1-i] = c == '1';
}
//ans = max(ans,tmp);
//cout <<ans<<endl;
for(int i = 0;i < n;++i){
if(!per[i]) {
ans = n-i;break;
}
}
da(r,sa,n,30);
calcheight(r,sa,n);
height[n] = 0;
sum[0] = per[sa[0]];
for(int i = 1;i < n;++i) sum[i] = sum[i-1] + per[sa[i]];
top = 0;
for(int i = 1;i <= n;i++){
if(!top || height[i] > height[stk[top].i]) stk[++top] = (P){i,1,0};
else{
int tmp = 0,forbids = 0;
while(top && height[stk[top].i] >= height[i]){
tmp += stk[top].w;
forbids = sum[i-1] - sum[i-1-tmp-1];
ans = max(ans,(tmp+1-forbids)*height[stk[top].i]);
--top;
}
stk[++top] = (P){i,tmp+1,0};
}
}
cout<<ans<<endl;
return 0;
}