原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html

题目传送门 - CF873F

题意

  给定长度为 $n$ 的字符串 $s$,以及给定这个字符串每一个位置是否 “禁止结尾” 的信息。

  一个字符串 $a$ 的价值为 $|a|\times f(a)$ 。

  其中 $f(a)$为 $a$ 在 $s$ 中的匹配次数(如果匹配的结尾为禁止结尾点,那么不算匹配成功)

  问在所有的字符串 $a$ 中,$\max(|a|\times f(a)$ 的值。

  $n\leq 2\times 10 ^5$

题解

  大概是好久没做 SAM 了,第一个想到的就是 SA 。其实用 SAM 做非常简单,不知道高到哪里去了……

  这里讲 SA 做法。

  首先考虑到 SA 对后缀开头点掌握的比较好,所以我们将原串翻转,把问题转化成开头禁止。

  然后对 $s$ 串跑一下 SA 。

  然后假装那些开头禁止的串不存在,就转化成一个经典的问题,直接单调栈搞定。

  至于单调栈原理,这里有一道类似的运用单调栈的例题。

  https://www.cnblogs.com/zhouzhendong/p/9026184.html

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005;
int n;
int SA[N],rank[N],tmp[N],height[N],tax[N];
int sum[N];
int st[N],top,pos[N];
char s[N],t[N];
void Sort(int n,int m){
for (int i=0;i<=m;i++)
tax[i]=0;
for (int i=1;i<=n;i++)
tax[rank[i]]++;
for (int i=1;i<=m;i++)
tax[i]+=tax[i-1];
for (int i=n;i>=1;i--)
SA[tax[rank[tmp[i]]]--]=tmp[i];
}
bool cmp(int rk[],int x,int y,int w){
return rk[x]==rk[y]&&rk[x+w]==rk[y+w];
}
void Suffix_Array(char s[],int n){
memset(SA,0,sizeof SA);
memset(tmp,0,sizeof tmp);
memset(rank,0,sizeof rank);
memset(height,0,sizeof height);
for (int i=1;i<=n;i++)
rank[i]=s[i],tmp[i]=i;
int m=234;
Sort(n,m);
for (int w=1,p=0;p<n;w<<=1,m=p){
p=0;
for (int i=n-w+1;i<=n;i++)
tmp[++p]=i;
for (int i=1;i<=n;i++)
if (SA[i]>w)
tmp[++p]=SA[i]-w;
Sort(n,m);
swap(rank,tmp);
rank[SA[1]]=p=1;
for (int i=2;i<=n;i++)
rank[SA[i]]=cmp(tmp,SA[i],SA[i-1],w)?p:++p;
}
for (int i=1,j,k=0;i<=n;height[rank[i++]]=k)
for (k=max(k-1,0),j=SA[rank[i]-1];s[i+k]==s[j+k];k++);
height[1]=0;
}
int main(){
scanf("%d",&n);
scanf("%s%s",s+1,t+1);
for (int i=1;i<=n/2;i++){
swap(s[i],s[n-i+1]);
swap(t[i],t[n-i+1]);
}
Suffix_Array(s,n);
for (int i=1;i<=n;i++)
if (t[SA[i]]=='1')
sum[i]=sum[i-1];
else
sum[i]=sum[i-1]+1;
LL ans=0;
for (int i=1;i<=n;i++)
if (t[i]=='0')
ans=max(ans,(LL)n-i+1);
top=1,st[top]=1,pos[top]=1;
height[n+1]=0;
for (int i=2;i<=n+1;i++){
int j=st[top],p=i;
while (height[j]>height[i]){
ans=max(ans,1LL*height[j]*(sum[i-1]-sum[pos[top]-2]));
p=pos[top];
j=st[--top];
}
st[++top]=i,pos[top]=p;
}
printf("%I64d",ans);
return 0;
}

  

Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)的更多相关文章

  1. Codeforces 1073G Yet Another LCP Problem $SA$+单调栈

    题意 给出一个字符串\(s\)和\(q\)个询问. 每次询问给出两个长度分别为\(k,l\)的序列\(a\)和序列\(b\). 求\(\sum_{i=1}^{k}\sum_{j=1}^{l}lcp(s ...

  2. CodeForces 873F Forbidden Indices 后缀数组

    忘了当时怎么做的了,先把代码贴上,保存一下后缀数组模板. #include <cstdio> #include <cstring> #include <algorithm ...

  3. Codeforces 802I Fake News (hard) (SA+单调栈) 或 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9026184.html 题目传送门 - Codeforces 802I 题意 求一个串中,所有本质不同子串的出现次 ...

  4. luogu2178/bzoj4199 品酒大会 (SA+单调栈)

    他要求的就是lcp(x,y)>=i的(x,y)的个数和a[x]*a[y]的最大值 做一下后缀和,就只要求lcp=i的了 既然lcp(x,y)=min(h[rank[x]+1],..,[h[ran ...

  5. BZOJ3238 [Ahoi2013]差异 SA+单调栈

    题面 戳这里 题解 考虑把要求的那个东西拆开算,前面一个东西像想怎么算怎么算,后面那个东西在建出\(height\)数组后相当于是求所有区间\(min\)的和*2,单调栈维护一波即可. #includ ...

  6. poj 3415 Common Substrings【SA+单调栈】

    把两个串中间加一个未出现字符接起来,然后求SA 然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献 两部分分别作 ...

  7. 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)

    补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...

  8. Codeforces 1156E Special Segments of Permutation(单调栈)

    可以用单调栈直接维护出ai所能覆盖到的最大的左右范围是什么,然后我们可以用这个范围暴力的去查询这个区间的是否有满足的点对,一个小坑点,要对左右区间的大小进行判断,只需要去枚举距离i最近的一段区间去枚举 ...

  9. Codeforces 316G3 Good Substrings 字符串 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010851.html 题目传送门 - Codeforces 316G3 题意 给定一个母串$s$,问母串$s$有 ...

随机推荐

  1. 转载:UML学习(三)-----序列图(silent)

    原文:http://www.cnblogs.com/silent2012/archive/2011/09/14/2172219.html UML的模型中可分为两种,动态模型和静态模型.用例图.类图和对 ...

  2. shell脚本学习系列之一---入门

    参考:http://me.52fhy.com/shell-book/ 待后续整理...

  3. laravel sql复杂语句,原生写法----连表分组

    ### 使用了临时表.又分组又连表的感觉好难写,使用拉 ravel 但是现在越来也相信,没解决一个新的难题,自己又进步了一点点 ### 原生的sql: select user_code, realna ...

  4. MinGW-w64非官方编译器集成安装包(很清楚)

    官方链接[编辑] MinGW 官方网站. SourceForge.net上的MinGW官方的下载站点(Win32系统). MinGW-w64官方的下载站点[编辑] MinGW-w64是2005年由On ...

  5. python多线程中锁的概念

    1 2 3 4 5 6 7 8 mutex = threading.Lock() #锁的使用 #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([time ...

  6. checkstyle.xml Code Style for Eclipse

    1. Code Templates [下载 Code Templates] 打开 Eclipse -> Window -> Preferences -> Java -> Cod ...

  7. Confluence 6 MySQL 创建数据库和数据库用户

    一旦你成功的安装和配置了 MySQL 数据库服务器,你需要为你的 Confluence 创建数据库和数据库用户: 在 MySQL 中以超级用户运行 'mysql' .默认的用户为 'root' 同时密 ...

  8. Confluence 6 自定义站点和空间布局

    你可以通过编辑布局文件来修改 Confluence 的外观和感觉(也可以被称为装饰).编辑这些文件将会允许你对整个 Confluence 站点的外观和感觉进行修改或者仅仅是一个独立的空间. 当你对一个 ...

  9. NIO(四)

    使用非直接缓冲区和直接缓冲区复制同一个文件,看一下时间差别 1.创建非直接缓冲区测试类 package com.cppdy.nio; import java.io.FileInputStream; i ...

  10. PDF怎么去除页眉页脚,PDF页眉页脚编辑方法

    我们在使用文件的时候需要编辑页眉页脚的时候,这个时候我们应该怎么做呢,相信别的文件大家都知道怎么编辑了,PDF文件大家都知道吗,最开始接触这个文件的时候小编觉得很难,之后找到技巧之后也并没有很难,今天 ...