BZOJ


\(Description\)

给定两个串\(S,T\)以及一个数\(k\),求\(T\)中有多少个子串,满足和\(S\)的编辑距离不超过\(k\)。
\(|S|+|T|\leq10^5,\ k\leq 5\)。

\(Solution\)

考虑枚举\(T\)的每个后缀\(i\)(注意后缀是指啥= =),求后缀\(i\)中有哪些前缀满足条件。
怎么处理编辑距离呢?\(k\)很小,直接搜。
设\(S,T\)分别匹配到\(x,y\)位置,可以用\(SA\)求\(LCP(x,y)\),然后直接跳到下一个不匹配位置。
如果\(S_x\neq T_y\),那么有三种选择:删掉\(T_y\to x,y+1\),在\(T_y\)前插入一个\(S_x\to x+1,y\),把\(T_y\)替换成\(S_x\to x+1,y+1\)。
所以\(DFS\)的复杂度是\(3^k\)的。
匹配完\(S\)串后,如果还剩下一些可用编辑距离\(rest\),显然此时前缀\([y-rest,y+rest]\)都满足条件,差分一下即可。注意这些前缀不要算重(一个位置只能算一次)。

复杂度\(O(n\log n+n3^k)\)。


//10296kb   3476ms
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
const int N=1e5+7;int na,nb,Now,L,R,sum[N];
char s[N];
struct Suffix_Array
{int sa[N],sa2[N],rk[N],tm[N],ht[N],Log[N],st[17][N];inline int LCP(int l,int r){l=rk[l], r=rk[r]; if(l>r) std::swap(l,r);++l; int k=Log[r-l+1];return std::min(st[k][l],st[k][r-(1<<k)+1]);}void Build(const char *s,const int n){int m=27,*x=rk,*y=sa2;for(int i=0; i<=m; ++i) tm[i]=0;for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]-'A'+1];for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];for(int i=n; i; --i) sa[tm[x[i]]--]=i;for(int k=1,p=0; k<n; k<<=1,m=p,p=0){for(int i=n-k+1; i<=n; ++i) y[++p]=i;for(int i=1; i<=n; ++i) if(sa[i]>k) y[++p]=sa[i]-k;for(int i=0; i<=m; ++i) tm[i]=0;for(int i=1; i<=n; ++i) ++tm[x[i]];for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i];std::swap(x,y), x[sa[1]]=p=1;for(int i=2; i<=n; ++i)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?p:++p;if(p>=n) break;}for(int i=1; i<=n; ++i) rk[sa[i]]=i;ht[1]=0;for(int i=1,k=0; i<=n; ++i){if(rk[i]==1) continue;if(k) --k;int p=sa[rk[i]-1];while(i+k<=n && p+k<=n && s[i+k]==s[p+k]) ++k;ht[rk[i]]=k;}st[0][1]=ht[1];for(int i=2; i<=n; ++i) Log[i]=Log[i>>1]+1, st[0][i]=ht[i];for(int j=1; j<=Log[n]; ++j)for(int t=1<<j-1,i=n-t; i; --i)st[j][i]=std::min(st[j-1][i],st[j-1][i+t]);}
}sa;inline void Upd(int l,int r)
{l=std::max(l,Now), r=std::min(r,nb), L=std::min(l,L), R=std::max(r+1,R);++sum[l], --sum[r+1];//注意可行前缀位置的限制(在Now~nb内)
}
void DFS(int x,int y,int rest)
{int t=sa.LCP(x,y+na+1);x+=t, y+=t;if(x>na||y>nb){int d=rest-(na-x+1);if(d>=0) Upd(y-1-d,y-1+d);return;}if(rest) --rest, DFS(x+1,y,rest), DFS(x,y+1,rest), DFS(x+1,y+1,rest);
}int main()
{int K; scanf("%d%s",&K,s+1);na=strlen(s+1), s[na+1]='[';scanf("%s",s+na+2), nb=strlen(s+na+2);const int n=na+nb+1; sa.Build(s,n);int ans=0;for(int i=1,delta=std::max(0,na-K); i+delta<=nb; ++i){Now=i, L=N, R=0, DFS(1,i,K);for(int j=L; j<=R; ++j) ans+=(sum[j]+=sum[j-1])>0;for(int j=L; j<=R; ++j) sum[j]=0;}printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/10336152.html

BZOJ.4340.[BJOI2015]隐身术(后缀数组 搜索)相关推荐

  1. BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组 + 贪心 + 细节

    Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串 ...

  2. BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 居然把后缀数组写成n^2的..我真厉害.. 想了无数种方法,最后发现就是 ...

  3. BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组

    4278: [ONTAK2015]Tasowanie Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 426  Solved: 199 [Submit ...

  4. bzoj 4278 [ONTAK2015]Tasowanie——后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4278 因为每次要放后缀较小的那个,所以把两个序列放在一起排序吧.改一改模板. 其实要改的地方 ...

  5. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2326  Solved: 1054 [Submit][Stat ...

  6. bzoj 2865 字符串识别——后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2865 做出 ht[ ] 之后,sa[ ] 上每个位置和它前面与后面取 LCP ,其中较大的长 ...

  7. 笨办法学 Python · 续 练习 22:后缀数组

    练习 22:后缀数组 原文:Exercise 22: Suffix Arrays 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 我想告诉你一个关于后缀数组的故事.在一段时间里, ...

  8. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

  9. UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)

    UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组.ST表) 连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题 ...

  10. 【BZOJ】1031: [JSOI2007]字符加密Cipher(后缀数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1031 很容易想到这就是将字符串复制到自己末尾然后后缀数组搞出sa然后按区间输出即可. 然后换了下模板 ...

最新文章

  1. 这7个开源技术,支撑起整个互联网时代
  2. “解决方案资源管理器”中不能自动选择正在编辑的文档
  3. Python SQLAlchemy
  4. 0821Cache Buffers chains与共享模式疑问4
  5. 【Servlet】监听器技术
  6. 菜鸟教程python3 mysql_python基础教程使用Python操作MySQL的小技巧
  7. Python 编程训练(3)
  8. 商品预约抢购实践及redis性能测试
  9. 一位程序员的十年工作总结,值得每位互联网人看
  10. jdk1.8下载安装教程
  11. VueJs 自定义过滤器使用总结
  12. 游戏服务器背包设计与开发
  13. 嵌入式软件工程师对linux要求,嵌入式软件工程师的必备知识
  14. 网络存储服务器系统价格比较,【网络存储器报价】四款不同的网络存储器,你会选择那一款?...
  15. 翻译:《Pro CSS and HTML Design Patterns》简介、总览和目录
  16. 正则表达式--replace
  17. STM32F103超声波HCSR04模块串口输出距离(附代码)
  18. Spark数据分区(partitionBy分区、partitioner获取分区方式、自定义分区)
  19. 每日一句英语 2012-9-15
  20. LeetCode 1 Two Sum——在数组上遍历出花样

热门文章

  1. 普通的dub的sdl配置
  2. python12306抢票_GitHub - versionzhang/python_12306: python 12306 抢票工具
  3. 计算机学院实验报告,大学计算机实验报告-EXCEL电子表格实验
  4. C++几个常用的排序
  5. 算法创作|栈的应用——括号匹配问题解决方法
  6. JavaScript中三元一次函数的解法
  7. 网付扫码点餐新福利,消费者点餐可获微信支付金币奖励
  8. SSL证书错误了怎么办?
  9. unity3d 地面印花_unity冬季场景地面地形白雪纹理材质贴图游戏素材Winter Ground Pack v1.1...
  10. bundle install 出现 'gem install mysql2 -v '0.3.15' succeeds before bunding '