Description

给定两个串A,B。请问B中有多少个非空子串和A的编辑距离不超过K?
所谓“子串”,指的是B中连续的一段。不同位置的内容相同的子串算作多个。
两个串之间的“编辑距离”指的是把一个串变成另一个串需要的最小的操作次数,
每次操作可以插入、删除或者替换一个字符。

Input

第一行一个非负整数K。接下来两行,每行一个由大写字母组成的字符串,分别表示A和B。

Output

输出一行一个整数,表示所求答案。

Sample Input

1
AAA
AABBAAB

Sample Output

5

HINT

对100%的数据,K≤5,两个字符串均非空,长度和小于10^5.

Solution

先把字符串拼起来建个后缀数组。

看到$k$不大,考虑枚举左端点搜索。

设状态$(x,y,z)$表示该考虑$S$串的$x$位置和$T$串的$y$位置,前面已经做了$k$次修改。

每层搜索开始先把$x$和$y$指针往后跳,跳的距离为后缀$x$和后缀$y$的$lcp$的长度。

如果有$x$或者$y$有一个到底了,就说明匹配上了。

设$d$表示剩下的操作次数,较显然的是$d=k-z-(len_S-x)$。

在我们手里还剩下$d$次操作次数的情况下,实际上合法结束位置不仅仅是$y-1$,而是$[y-1-d,y-1+d]$这个区间。这个区间的长度最多只有$2\times k +1$,可以用个前缀和统计一下。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#define N (200009)
#define LL long long
using namespace std; int n,m=,k,sl,tl,L,R,now,sum[N];
int wa[N],wb[N],wt[N];
int ST[N][],LOG2[N];
int SA[N],Rank[N],Height[N];
LL ans;
char r[N],s[N],t[N]; bool cmp(int *y,int a,int b,int k)
{
int arank1=y[a];
int brank1=y[b];
int arank2=a+k>=n?-:y[a+k];
int brank2=b+k>=n?-:y[b+k];
return arank1==brank1 && arank2==brank2;
} void Build_SA()
{
int *x=wa,*y=wb;
for (int i=; i<m; ++i) wt[i]=;
for (int i=; i<n; ++i) ++wt[x[i]=r[i]];
for (int i=; i<m; ++i) wt[i]+=wt[i-];
for (int i=n-; i>=; --i) SA[--wt[x[i]]]=i; for (int j=; j<=n; j<<=)
{
int p=;
for (int i=n-j; i<n; ++i) y[p++]=i;
for (int i=; i<n; ++i) if (SA[i]>=j) y[p++]=SA[i]-j; for (int i=; i<m; ++i) wt[i]=;
for (int i=; i<n; ++i) ++wt[x[y[i]]];
for (int i=; i<m; ++i) wt[i]+=wt[i-];
for (int i=n-; i>=; --i) SA[--wt[x[y[i]]]]=y[i]; m=; swap(x,y); x[SA[]]=;
for (int i=; i<n; ++i)
x[SA[i]]=cmp(y,SA[i],SA[i-],j)?m-:m++;
if (m>=n) break;
}
} void Build_Height()
{
for (int i=; i<n; ++i) Rank[SA[i]]=i;
int k=;
for (int i=; i<n; ++i)
{
if (!Rank[i]) continue;
if (k) k--;
int j=SA[Rank[i]-];
while (r[i+k]==r[j+k]) k++;
Height[Rank[i]]=k;
}
} void Build_ST()
{
for (int i=; i<=n; ++i) LOG2[i]=LOG2[i>>]+;
for (int i=; i<n; ++i)
ST[i][]=Height[i];
for (int j=; j<=; ++j)
for (int i=; i+(<<j)-<n; ++i)
ST[i][j]=min(ST[i][j-],ST[i+(<<j-)][j-]);
} int Query(int l,int r)
{
int k=LOG2[r-l+];
return min(ST[l][k],ST[r-(<<k)+][k]);
} void DFS(int x,int y,int z)
{
if (z>k) return;
int l=Rank[x],r=Rank[y];
if (l>r) swap(l,r);
int lcp=Query(l+,r);
x+=lcp; y+=lcp;
if (x==sl || y==n)
{
int d=k-z-(sl-x);
if (d<) return;
int l=max(y--d,now),r=min(y-+d,n-);
L=min(l,L); R=max(r+,R);
sum[l]++; sum[r+]--;
return;
}
DFS(x+,y,z+); DFS(x,y+,z+); DFS(x+,y+,z+);
} int main()
{
scanf("%d%s%s",&k,s,t);
sl=strlen(s); tl=strlen(t);
for (int i=; i<sl; ++i) r[n++]=s[i]; r[n++]='#';
for (int i=; i<tl; ++i) r[n++]=t[i];
Build_SA(); Build_Height(); Build_ST();
for (int i=; i<tl; ++i)
{
now=sl+i+, L=n-,R=;
DFS(,sl+i+,);
for (int j=L; j<=R; ++j) ans+=(sum[j]+=sum[j-])>;
for (int j=L; j<=R; ++j) sum[j]=;
}
printf("%lld\n",ans);
}

BZOJ4340:[BJOI2015]隐身术(后缀数组,ST表,DFS)的更多相关文章

  1. [BZOJ4340][BJOI2015]隐身术(后缀数组)

    考虑到K很小,于是可以暴搜每次用的是哪种操作,跳过AB相等的字符可以用SA求LCP加速. 主要流程就是,枚举B的每个后缀,对每个后缀统计合法前缀个数.DFS搜索每次决策,用SA跳过相同字符,当A或B匹 ...

  2. SPOJ 687 Repeats(后缀数组+ST表)

    [题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...

  3. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

  4. BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay

    BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...

  5. UVA10829 L-Gap Substrings(后缀数组+ST表)

    后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...

  6. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  7. 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分

    4310: 跳蚤 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 180  Solved: 83[Submit][Status][Discuss] De ...

  8. UVA 11475 Extend to Palindrome(后缀数组+ST表)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...

  9. Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)

    The repetition number of a string is defined as the maximum number \(R\) such that the string can be ...

随机推荐

  1. EF访问数据库报“ExecuteReader 要求已打开且可用的 Connection。连接的当前状态为已关闭。”错误

    我发生这个问题的原因是因为我用EF访问数据库时用的用到了两用方式,如下图 第一种方式访问时不会出现此错误,出现错误的是第二种方式,下图是dal层代码 其中红框中的代码是出现错误之后改正的代码,也就是说 ...

  2. 转载 HashSet用法

    NET 3.5在System.Collections.Generic命名空间中包含一个新的集合类:HashSet<T>.这个集合类包含不重复项的无序列表.这种集合称为“集(set)”.集是 ...

  3. Java基础——iO(二)

    接着上一篇,继续做学习笔记.学IO这块,突然找到一点好处,好像以后操作电脑,尤其是电脑里的文件啥的,可以很少的用鼠标了.添加.修改.删除啥的,几行代码就可以搞定了.这只是我一个初学者的一点小心思,IO ...

  4. 聊聊Java内存模型

    一.Java内存模型 硬件处理 电脑硬件,我们知道有用于计算的cpu.辅助运算的内存.以及硬盘还有进行数据传输的数据总线.在程序执行中很多都是内存计算,cpu为了更快的进行计算会有高速缓存,最后同步至 ...

  5. Hadoop集群动态服役新的数据节点&&退役数据节点

    备注:新添的机器为hadoop05,现有hadoop01.hadoop02.hadoop03.hadoop04 环境准备: 1.先克隆一台和集群中一样的机器 2.修改机器ip和主机名称 3.删除原来的 ...

  6. Linux常用基本命令(cut)

    cut命令 作用:从文件的每一行剪切字节,字符或者字段,类似与编程语言中的字符串截取函数 格式:cut [option] [file] -b:仅显示行中指定直接范围的内容: -c:仅显示行中指定范围的 ...

  7. Codeforces834A

    A. The Useless Toy time limit per test:1 second memory limit per test:256 megabytes input:standard i ...

  8. BZOJ3884(SummerTrainingDay04-C 欧拉定理)

    上帝与集合的正确用法 根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天,  上帝创造了一个世界的基本元素,称做“元”. 第二天,  上帝创造了一个新的元素,称作“α”.“α”被定义为“元 ...

  9. python-原型模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明 原型模式关注的是大量相同对象或相似对象的创建问题,意图在于通过复制一个已经存在的实 ...

  10. CSS3和HTML5新增特性及使用(保留方便查看)

    CSS3 1.边框图片 border-image: url(test.png) 10/10px;  outline:10px solid #ff0;outline-offset:15px;边框的边框, ...