codeforces F.Forbidden Indices后缀数组+LCP
来源:互联网 发布:iphone手机壳品牌知乎 编辑:程序博客网 时间:2024/06/06 12:37
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).
5ababa00100
5
5ababa00000
6
5ababa11111
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;}
- codeforces F.Forbidden Indices后缀数组+LCP
- 后缀数组求LCP
- 后缀数组LCP + 二分
- hdu4691 后缀数组求lcp
- ural1297Palindrome (后缀数组+lcp)
- PKU 3261 Milk Pattern - 后缀数组+LCP
- HDU 4691(后缀数组+lcp)水题
- hdu 4691 后缀数组+RMQ+LCP
- (模板)后缀数组(lcp和rmq)
- 后缀数组,任意两点间LCP
- HDU 4691 Front Compression [后缀数组] [LCP]
- SPOJ687 Repeats (后缀数组+lcp)
- poj3693(后缀数组+lcp+rmq)
- HDU 6194 后缀数组+lcp+rmq
- 后缀数组 + LCP(最长公共前缀)
- POJ2774 Long Long Message 【后缀数组lcp】
- CodeForces 653F Paper task(rmq+二分+后缀数组)
- 根据后缀树LCA计算后缀数组及其LCP
- 插入排序
- AngularJS输入内容到公告窗,敏感字以*代替
- 自定义可拖拽的父容器
- 数据库的基本构成和原理-2
- 684. Redundant Connection
- codeforces F.Forbidden Indices后缀数组+LCP
- 搜索页面实现总结
- int *和int[]共同点和区别
- 手把手教你搭建FastDFS集群(下)
- 基本数据类型的隐式转换
- JAVA SE — Day 05
- operator.itermgetter() (Python)
- 我的文学博客(为爱而生,生生不息)
- 小练习:数组元素的交换