codeforces F.Forbidden Indices后缀数组+LCP

来源:互联网 发布:iphone手机壳品牌知乎 编辑:程序博客网 时间:2024/06/06 12:37

F. Forbidden Indices
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 |af(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 aaaaa is aa and index 3 is forbidden, then f(a) = 2 because there are three occurences of a in s (starting in indices 12 and 3), but one of them (starting in index 2) ends in a forbidden index.

Calculate the maximum possible value of |af(a) you can get.

Input

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).

Output

Print the maximum possible value of |af(a).

Examples
input
5ababa00100
output
5
input
5ababa00000
output
6
input
5ababa11111
output
0

题解:

某些位置不可以作为串的结束位置,这样不好做,把这个字符串反序。然后限制条件就变成了有的字符不能作为串的开始。

然后对字符串求后缀数组sa和高度数组height。

然后的话,求|a|*f(a)的值就对应到了height数组里面的最大矩形面积,用单调栈的方法进行处理,但是有限制条件,即矩形块中有的部分是以forbidden为开始的后缀,不能被算进去,所以还要减去这些被限制的后缀串。用前缀sum维护即可在O(1)的时间内减去限制串数目。


代码:

#include <bits/stdc++.h>using namespace std;#define int long longstruct 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;} 


原创粉丝点击