Codeforces 316G3 Good Substrings 字符串 SAM
原文链接http://www.cnblogs.com/zhouzhendong/p/9010851.html
题目传送门 - Codeforces 316G3
题意
给定一个母串$s$,问母串$s$有多少本质不同的子串$t$是“好”的。
一个字符串$t$是好的,仅当$t$满足了所有的$n$个条件。
第$i$个条件用一个三元组$(p_i,L_i,R_i)$来描述。
其中$p_i$为一个字符串,$L_i,R_i$为整数,且$L_i\leq R_i$。
仅当字符串$t$在$p_i$中出现次数在$L_i$到$R_i$之间时,它是"好"的。
$|s|,|p_i|\leq 5\times 10^4,n\leq 10$
题解
考虑把输入的$n+1$个字符串用特殊字符隔开,并练成一个串。
为了方便,我们将母串$s$放在第一个,$n$条规则中的字符串依次连续。
我们定义数组$tot[i][j]$表示后缀自动机状态$i$的$Right$集合中有多少个位置处于第$j$个串。其中母串为第$0$个串,$p_i$为第$i$个串。
这个可以通过基数排序+$dp$来搞定。
然后我们分状态统计。
对于状态$i$,如果$tot[i][0]=0$,那么说明这个状态所表示的一些串不存在于母串中,所以可以跳过。
否则$tot[i][0]>0$,这个状态所表示的一些串存在于母串中。由于母串中没有特殊的字符,所以这个状态所表示的一些串也没有特殊字符,所以,对于已经得到的计数$tot[i][1\cdot n]$中也没有统计到包含特殊字符的子串。
如果当前状态被计入,那么需要满足所有的$n$个条件,即$\forall 1\leq j\leq n,\ \ L_j\leq tot[i][j]\leq R_j$。当前状态包含的本质不同的串的个数显然为$Max(i)-Min(i)+1=Max(i)-Max(fa(i))$。加到答案里就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=550005;
int n,m,L[15],R[15];
int size=1,root=1,last=1;
int tax[N<<1],id[N<<1];
LL tot[N<<1][12];
char s[N];
struct SAM{
int Next[27],fa,Max;
}t[N<<1];
void extend(int c,int id){
int p=last,np=++size,q,nq;
tot[np][id]++;
t[np].Max=t[p].Max+1;
for (;!t[p].Next[c];p=t[p].fa)
t[p].Next[c]=np;
q=t[p].Next[c];
if (t[q].Max==t[p].Max+1)
t[np].fa=q;
else {
nq=++size;
t[nq]=t[q],t[nq].Max=t[p].Max+1;
t[q].fa=t[np].fa=nq;
for (;t[p].Next[c]==q;p=t[p].fa)
t[p].Next[c]=nq;
}
last=np;
}
int main(){
t[0].Max=-1;
for (int i=0;i<27;i++)
t[0].Next[i]=1;
scanf("%s",s);
m=strlen(s);
for (int i=0;i<m;i++)
extend(s[i]-'a',0);
scanf("%d",&n);
for (int i=1;i<=n;i++){
extend(26,n+1);
scanf("%s%d%d",s,&L[i],&R[i]);
m=strlen(s);
for (int j=0;j<m;j++)
extend(s[j]-'a',i);
}
for (int i=1;i<=size;i++)
tax[t[i].Max]++;
for (int i=1;i<=size;i++)
tax[i]+=tax[i-1];
for (int i=1;i<=size;i++)
id[tax[t[i].Max]--]=i;
LL ans=0;
for (int i=size;i>=2;i--){
int x=id[i];
for (int j=0;j<=n;j++)
tot[t[x].fa][j]+=tot[x][j];
if (tot[x][0]==0)
continue;
bool flag=1;
for (int j=1;flag&&j<=n;j++)
flag&=L[j]<=tot[x][j]&&tot[x][j]<=R[j];
if (flag)
ans+=t[x].Max-t[t[x].fa].Max;
}
printf("%I64d",ans);
return 0;
}
Codeforces 316G3 Good Substrings 字符串 SAM的更多相关文章
- Codeforces 1276F - Asterisk Substrings(SAM+线段树合并+虚树)
Codeforces 题面传送门 & 洛谷题面传送门 SAM hot tea %%%%%%% 首先我们显然可以将所有能够得到的字符串分成六类:\(\varnothing,\text{*},s, ...
- Codeforces 235C Cyclical Quest 字符串 SAM KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF235C.html 题目传送门 - CF235C 题意 给定一个字符串 $s$ ,多组询问,每组询问的形式为 ...
- Codeforces 452E Three strings 字符串 SAM
原文链接https://www.cnblogs.com/zhouzhendong/p/CF542E.html 题目传送门 - CF452E 题意 给定三个字符串 $s1,s2,s3$ ,对于所有 $L ...
- Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...
- Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...
- Codeforces Round #294 (Div. 2)D - A and B and Interesting Substrings 字符串
D. A and B and Interesting Substrings time limit per test 2 seconds memory limit per test 256 megaby ...
- codeforces #271D Good Substrings
原题链接:http://codeforces.com/problemset/problem/271/D 题目原文: D. Good Substrings time limit per test 2 s ...
- 【Codeforces 1037H】Security(SAM & 线段树合并)
Description 给出一个字符串 \(S\). 给出 \(Q\) 个操作,给出 \(L, R, T\),求字典序最小的 \(S_1\),使得 \(S^\prime\) 为\(S[L..R]\) ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
随机推荐
- liux三剑客grep 正则匹配
001正则匹配(大部分需要转义) ‘^‘: 锚定行首 '$' : 锚定行尾 [0-9] 一个数字 [^0-9] 除去数字所有,^出现在[]这里表示取反 [a-z] [A-Z] [a-Z] \s 匹配空 ...
- Android 应用防止被二次打包指南
前言 “Android APP二次打包”则是盗版正规Android APP,破解后植入恶意代码重新打包.不管从性能.用户体验.外观它都跟正规APP一模一样但是背后它确悄悄运行着可怕的程序,它会在不知不 ...
- Java代码自动部署
注:本文来源于<it小熊> [ ①Java代码自动部署-总结简介] 代码部署是每一个软件开发项目组都会有的一个流程,也是从开发环节到发布功能必不可少的环节.对于Java开发者来说,Java ...
- vue三大框架
vue 前端三大新框架: Angular.js------Google研发 缺点: 学习成本高.最早研发 严谨 React.js facebook.com (脸书)自主研发 开源 j ...
- LeetCode(71):简化路径
Medium! 题目描述: 给定一个文档 (Unix-style) 的完全路径,请进行路径简化. 例如,path = "/home/", => "/home&quo ...
- 添加按钮 table增加一行 删减按钮 table去掉一行
需求描述:做的一个AA新增功能,同时可以为这个即将新增的AA添加内容,而且AA的内容默认展示一行列表,点击添加按钮后出现下一行列表 解决思路:页面首先展示一个表头和列表的一行,作为默认展示的一行列表, ...
- 怎么加密接口防止,API外部调用?
服务器端与客户端各自会存储一个TOKEN,这个TOKEN我们为了防止反编译是用C语言来写的一个文件并做了加壳和混淆处理.在客户端访问服务器API任何一个接口的时候,客户端需要带上一个特殊字段,这个字段 ...
- AI学习吧-支付宝支付
支付宝支付流程 1.接收前端发过来的贝里数和结算金额 2.检查贝里数是否够用 3.获取结算中心的课程并应用优惠券 4.应用未绑定课程的优惠券 5.判断总价格减去优惠券价格是否等于实际支付金额 6.生成 ...
- Ubuntu下创建桌面快捷方式(以Pycharm为例)
之后要在Ubuntu虚拟机上玩PyTorch,安装了Pycharm. 然而每次打开Pycharm需要在其bin目录下进入终端,然后输入sh pycharm.sh,很麻烦.既然Ubuntu是桌面系统,为 ...
- 011-Python-进程、线程于协程
1.进程与线程 进程: 一个程序要运行时所需的所有资源的集合: 一个进程至少需要一个线程,这个线程称为主线程,一个进程里可以包含多个线程: cpu 核数越多,代表着你可以真正并发的线程越多2个进程之间 ...