博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【SAM】loj#6401. 字符串
阅读量:5134 次
发布时间:2019-06-13

本文共 2880 字,大约阅读时间需要 9 分钟。

网上有篇题解写的是线段树合并维护求值?

题目描述

  有一个只包含小写字母,长度为 $n$ 的字符串 $S$ 。有一些字母是好的,剩下的是坏的。

  定义一个子串 $S_{l\ldots r}$是好的,当且仅当这个子串包含不超过 $k$ 个坏的字母。

  求有多少个不同的满足以下要求的字符串 $T$ :

  • $T$ 作为 $S$ 的子串出现过。
  • 存在一个 $T$ 出现的位置 $[l,r]$ ,满足 $S_{l\ldots r}$​ 是好的。

输入格式

  第一行有一个字符串 $S$ 。

  第二行有一个字符串 $B$ 。若 $B_i=‘1’$ 则表示 $S_i$​ 是好的,否则表示 $S_i$ 是坏的。

  第三行有一个整数 $k$ 。

输出格式

  一个整数:答案。

数据范围与提示

  子任务 $1$($10$ 分):$n\leq 10$。

  子任务 $2$($10$ 分):$n\leq 100$。

  子任务 $3$($10$ 分):$n\leq 1000$。

  子任务 $4$($10$ 分):$n\leq 100000,k=n$。

  子任务 $5$($10$ 分):$n\leq 100000,k=0$。

  子任务 $6$($20$ 分):$n\leq 100000$,若$S_i=S_j$​,则$B_i=B_j$​。

  子任务 $7$($30$ 分):$n\leq 100000$。

  对于 $100\%$ 的数据:$1\leq n\leq {10}^5,0\leq k\leq {10}^5$, $S$ 只包含小写字母。

  题目来源:全是水题的GDOI模拟赛 by yww


题目分析

定位:比较模板的SAM题(然而我一个月前并不会SAM)

题意即求满足一定条件的若干个字符串里本质不同的子串个数。当然这里的“一定条件”比较特殊,是连续的一段子串。(如果这里的“一定条件”字符串是若干个互不相干的串,似乎就需要“广义后缀自动机”来处理了)

既然对于每一个新增的节点,其合法的子串都有一个左边界,那么在SAM里处理的时候,就可以对每一节点加一个权值$mx[u]$表示该节点的最长合法扩展长度。这个权值的作用就在于建完自动机后的$calc()$,原先数本质不同的子串个数是这样的: ans += len[p]-len[fa[p]]; 现在就是 ans += std::max(std::min(mx[p], len[p])-len[fa[p]], 0); 。记得注意一下extend里对mx的转移。

1 #include
2 const int maxn = 200035; 3 4 int n,lim,sum[maxn],size[maxn],cnt[maxn],pos[maxn]; 5 long long ans; 6 struct SAM 7 { 8 int ch[maxn][27],fa[maxn],len[maxn],mx[maxn],lst,tot; 9 void init()10 {11 lst = tot = 1;12 }13 void extend(int c, int v)14 {15 int p = lst, np = ++tot;16 lst = np, len[np] = len[p]+1, mx[np] = v; //len[p+1] Here  居然打成标红的这个17 for (; p&&!ch[p][c]; p=fa[p]) ch[p][c] = np;18 if (!p) fa[np] = 1;19 else{20 int q = ch[p][c];21 if (len[p]+1==len[q]) fa[np] = q;22 else{23 int nq = ++tot;24 len[nq] = len[p]+1, mx[nq] = mx[q];25 memcpy(ch[nq], ch[q], sizeof ch[q]);26 fa[nq] = fa[q], fa[q] = fa[np] = nq;27 for (; p&&ch[p][c]==q; p=fa[p])28 ch[p][c] = nq;29 }30 }31 }32 void calc()33 {34 for (int i=1; i<=tot; i++) ++cnt[len[i]];35 for (int i=1; i<=tot; i++) cnt[i] += cnt[i-1];36 for (int i=1; i<=tot; i++) pos[cnt[len[i]]] = i, --cnt[len[i]];37 for (int i=tot; i; i--)38 {39 int p = pos[i];40 mx[fa[p]] = std::max(mx[fa[p]], mx[p]); 41 ans += std::max(std::min(mx[p], len[p])-len[fa[p]], 0);42 }43 }44 }f;45 char s[maxn],t[maxn];46 47 int main()48 {49 scanf("%s%s%d",s+1,t+1,&lim);50 n = strlen(s+1);51 f.init();52 for (int i=1, j=0; i<=n; i++)53 {54 sum[i] = (t[i]=='0')+sum[i-1];55 while (sum[i]-sum[j] > lim) ++j;56 f.extend(s[i]-'a'+1, i-j);57 }58 f.calc();59 printf("%lld\n",ans);60 return 0;61 }

 

 

END

转载于:https://www.cnblogs.com/antiquality/p/10511165.html

你可能感兴趣的文章
软件是天时、地利、人和的产物!
查看>>
python定时清空本目录下除本脚本外的全部文件
查看>>
【PHP】在目标字符串指定位置插入字符串
查看>>
【JS】jQuery设置定时器,访问服务器(PHP示例)配合微信、支付宝原生支付,跳转web网页...
查看>>
实验四2
查看>>
VS2012+Win7网站发布详细步骤
查看>>
Android现学现用第十一天
查看>>
Bin Packing 装箱问题——NPH问题的暴力枚举 状压DP
查看>>
多路复用
查看>>
python 列表
查看>>
Python数据可视化之Pygal(雷达图)
查看>>
Django组件--cookie与session
查看>>
12. javacript高级程序设计-DOM2和DOM3
查看>>
Centos7安装vsftpd (FTP服务器)
查看>>
当前主流读取Excel技术对比
查看>>
js-格式化数字保留两位小数-带千分符
查看>>
【Java】forward & redirect 的差异
查看>>
Java学习笔记--字符串和文件IO
查看>>
【BZOJ1951】古代猪文(CRT,卢卡斯定理)
查看>>
poj 2823 线段树
查看>>