考虑到K很小,于是可以暴搜每次用的是哪种操作,跳过AB相等的字符可以用SA求LCP加速。

主要流程就是,枚举B的每个后缀,对每个后缀统计合法前缀个数。DFS搜索每次决策,用SA跳过相同字符,当A或B匹配到结尾时统计答案。

每次某个串匹配到结尾时,B中的某个区间的前缀都会合法,注意到这些合法的前缀长度与A长度相差一定不超过K,于是用一个2*K+1的差分数组记录答案即可。复杂度$O(n\log n+n3^K)$

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6
 7 const int N=200010;
 8 int K,m,na,nb,n,d,ans,lg[N],h[N],c[N],x[N],y[N],sa[N],rk[N],st[N][20];
 9 char s[N],A[N],B[N];
10
11 bool Cmp(int a,int b,int l){ return y[a]==y[b] && y[a+l]==y[b+l]; }
12
13 void getSA(int m){
14     memset(y,0,sizeof(y));
15     rep(i,0,m) c[i]=0;
16     rep(i,1,n) c[x[i]=s[i]]++;
17     rep(i,1,m) c[i]+=c[i-1];
18     for (int i=n; i; i--) sa[c[x[i]]--]=i;
19     for (int k=1,p=0; p<n; k<<=1,m=p){
20         p=0; rep(i,n-k+1,n) y[++p]=i;
21         rep(i,1,n) if (sa[i]>k) y[++p]=sa[i]-k;
22         rep(i,0,m) c[i]=0;
23         rep(i,1,n) c[x[y[i]]]++;
24         rep(i,1,m) c[i]+=c[i-1];
25         for (int i=n; i; i--) sa[c[x[y[i]]]--]=y[i];
26         rep(i,0,n) y[i]=x[i]; p=1; x[sa[1]]=1;
27         rep(i,2,n) x[sa[i]]=Cmp(sa[i],sa[i-1],k)?p:++p;
28     }
29 }
30
31 void getH(){
32     rep(i,1,n) rk[sa[i]]=i; int k=0;
33     rep(i,1,n){
34         for (int j=sa[rk[i]-1]; j+k<=n && i+k<=n && s[i+k]==s[j+k]; k++);
35         h[rk[i]]=k; if (k) k--;
36     }
37 }
38
39 void init(){
40     lg[1]=0; rep(i,2,n) lg[i]=lg[i>>1]+1;
41     rep(i,1,n) st[i][0]=h[i];
42     rep(i,1,19) rep(j,1,n-(1<<i)+1) st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
43 }
44
45 int lcp(int l,int r){
46     int x=rk[l],y=rk[r+na+1];
47     if (x>y) swap(x,y);
48     x++; int t=lg[y-x+1];
49     return min(st[x][t],st[y-(1<<t)+1][t]);
50 }
51
52 void col(int l,int r){ l=max(l,d); r=min(r,nb); c[K-(na-(l-d+1))+1]++; c[K-(na-(r-d+1))+2]--; }
53
54 void dfs(int x,int y,int z){
55     int t=lcp(x,y); x+=t; y+=t;
56     if (x>na || y>nb){
57         int c=K-z-(na-x+1);
58         if (c>=0) col(y-1-c,y-1+c);
59         return;
60     }
61     if (z==K) return;
62     dfs(x+1,y,z+1); dfs(x,y+1,z+1); dfs(x+1,y+1,z+1);
63 }
64
65 int main(){
66     freopen("bzoj4340.in","r",stdin);
67     freopen("bzoj4340.out","w",stdout);
68     scanf("%d%s%s",&K,A+1,B+1); m=2*K+1;
69     na=strlen(A+1); nb=strlen(B+1);
70     rep(i,1,na) s[++n]=A[i]; s[++n]='#';
71     rep(i,1,nb) s[++n]=B[i];
72     getSA(300); getH(); init();
73     for (d=1; d<=nb; d++){
74         rep(j,1,m) c[j]=0;
75         dfs(1,d,0);
76         rep(j,1,m){
77             c[j]+=c[j-1];
78             if (c[j]) ans++;
79         }
80     }
81     printf("%d\n",ans);
82     return 0;
83 }

转载于:https://www.cnblogs.com/HocRiser/p/9965749.html

[BZOJ4340][BJOI2015]隐身术(后缀数组)相关推荐

  1. 寻找一个字符串的重复子串 后缀数组

    什么是后缀数组 令字符串 S=S[1]S[2]...S[n]S=S[1]S[2]...S[n]{\displaystyle S=S[1]S[2]...S[n]} , S[i,j]S[i,j]{\dis ...

  2. 【2012百度之星/资格赛】H:用户请求中的品牌 [后缀数组]

    时间限制: 1000ms 内存限制: 65536kB 描述 馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到一些很奇葩的词汇.在比方说"johnsonj ...

  3. Boring counting HDU - 3518 (后缀数组)

    Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串,求出其中出现两次及以上的子串个数,要 ...

  4. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  5. 后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)

    题目链接 题目大意: 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小!! sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_ ...

  6. 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]

    题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...

  7. [Ahoi2013]差异[后缀数组+单调栈]

    链接 解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i< ...

  8. poj2217详解 ( 后缀数组 + 高度数组 )

    题目大概意思就是 给两个字符串,求最长公共字符串子串长度 我们可以考虑用后缀数组和高度数组 一个字符串 中 最长的两个相同字符串长度, 不就是 后缀数组中相邻两个后缀的最长公共前缀, 不就是 高度数组 ...

  9. 树链剖分 + 后缀数组 - E. Misha and LCP on Tree

    E. Misha and LCP on Tree Problem's Link Mean: 给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. analyse: ...

  10. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

最新文章

  1. Web前端学习技巧有哪些?本文给你答案
  2. 纯属恶搞--javascript的 c#用法
  3. ios 不被遮挡 阴影_解决ios10导航栏底部阴影线条隐藏失效问题
  4. 在python中使用什么工具管理模块_怎么使用Python pip(管理模块工具)
  5. OC基础1:一些基本概念
  6. gnome boxes_如何使用GNOME Boxes的快照功能
  7. 试用阿里开源的Arthas小记
  8. 小马激活软件下载,当心伪小马,有病毒
  9. 软件测试工程师面试技巧---问答篇
  10. 帆软日期格式转换_FineReport中日期时间函数使用总结
  11. cad卸载不干净_还怕软件卸载不干净吗?试试它:Revo Uninstaller Pro
  12. 2022年湖北劳务资质如何办理?劳务资质不分等级
  13. 怎么把mp4转换成mp3?
  14. Python下载库pip pygame
  15. 国内手机市场寒风持续,华为与OV竞争将更激烈
  16. 移动端web设计尺寸_移动端之Web及app设计尺寸
  17. Linux下硬盘加密
  18. Access安全吗?Access安全性之QA详解
  19. CSU2020期中测试模拟题1 问题 B: 小帅要缴税
  20. 【题解】LuoGu4611:[COI2012] TRAMPOLIN

热门文章

  1. 让你两分钟明白什么是ERP
  2. 走近图灵奖大师David Patterson开挂的人生
  3. unity渲染篇:画面亮度、饱和度、对比度调整
  4. 【BZOJ3197】[Sdoi2013]assassin 树同构+动态规划+KM
  5. RabbitMQ之延迟队列
  6. 图神经网络(GNN)资源帖视频及必读论文
  7. Python测试:快乐的数字
  8. ResizeObserver loop limit exceeded报错解决方案
  9. 股票学习-量柱和k线-第一天
  10. 举个栗子!Tableau 技巧(185):实现多度量嵌套排序