[TJOI2017]DNA——后缀数组求LCP
Posted ylsoi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TJOI2017]DNA——后缀数组求LCP相关的知识,希望对你有一定的参考价值。
题目大意:
给定一个文本串和一个模式串,求文本串中有多少个连续的子串和模式串相差不超过三个字符。
思路:
算是一道后缀数组的模板题。
直接做lcp,然后遇到匹配不上的就跳,跳的次数不能超过三次。
具体地,将两个字符串连在一起,中间加一个分隔符,然后求出height,用rmq维护height数组的区间最小值即可。
/*=======================================
* Author : ylsoi
* Time : 2019.2.5
* Problem : luogu3763
* E-mail : [email protected]
* ====================================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<" "
#define fi first
#define se second
#define mk make_pair
#define pb push_back
typedef long long ll;
using namespace std;
void File(){
freopen("luogu3763.in","r",stdin);
freopen("luogu3763.out","w",stdout);
}
template<typename T>void read(T &_){
_=0; T fl=1; char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())_=(_<<1)+(_<<3)+(ch^'0');
_*=fl;
}
const int maxn=2e5+10;
int T;
int n,m;
char s[maxn];
int sz,sa[maxn],tp[maxn],rk[maxn],tax[maxn],height[maxn];
int st[maxn][21],Log[maxn];
void radix_sort(){
REP(i,1,sz)tax[i]=0;
REP(i,1,n)++tax[rk[i]];
REP(i,1,sz)tax[i]+=tax[i-1];
DREP(i,n,1)sa[tax[rk[tp[i]]]--]=tp[i];
}
void suffix_sort(){
sz=26;
REP(i,1,n)rk[i]=s[i]-'A'+1,tp[i]=i;
radix_sort();
for(int w=1,p=0;w<n;w<<=1){
p=0;
REP(i,1,w)tp[++p]=n-w+i;
REP(i,1,n)if(sa[i]>w)tp[++p]=sa[i]-w;
radix_sort();
swap(rk,tp);
rk[sa[1]]=p=1;
REP(i,2,n)
if(tp[sa[i-1]]==tp[sa[i]] && tp[sa[i-1]+w]==tp[sa[i]+w])rk[sa[i]]=p;
else rk[sa[i]]=++p;
sz=p;
if(sz==n)break;
}
}
void get_height(){
int k=0;
REP(i,1,n){
if(k)--k;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k])++k;
height[rk[i]]=k;
}
}
void init_st(){
REP(i,1,n)st[i][0]=height[i];
REP(j,1,Log[n])REP(i,1,n-(1<<j)+1)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int lcp(int x,int y){
x=rk[x],y=rk[y];
if(x>y)swap(x,y);
++x;
int d=Log[y-x+1];
return min(st[x][d],st[y-(1<<d)+1][d]);
}
int main(){
File();
REP(i,2,2e5)Log[i]=Log[i>>1]+1;
read(T);
while(T--){
scanf("%s",s+1);
m=strlen(s+1)+1;
s[m]='Z';
scanf("%s",s+m+1);
n=strlen(s+1);
suffix_sort();
get_height();
init_st();
int ans=0;
REP(i,1,m-n+m){
int p=0,len;
REP(j,1,4){
len=lcp(i+p,m+1+p);
p+=len;
if(p==n-m){++ans; break;}
else ++p;
}
}
printf("%d
",ans);
}
return 0;
}
以上是关于[TJOI2017]DNA——后缀数组求LCP的主要内容,如果未能解决你的问题,请参考以下文章