BZOJ 4892 DNA (sa+暴力)

给你一个母串 和 一个子串 问母串中有多少个子串更改不超过三个字母 可以和子串相匹配。

做法: 把母串和子串连起来建sa数组 然后 对母串的开头 和子串的开头进行枚举,如果首字母相同则求下一个跳到当前位置+lcp(母串当前位置,子串当前位置) 然后继续往下比较 最多只要跳不超过3次 就可以完成一次 开头的枚举 

建sa O(T*nlog(n))  n为母串加子串的长度

暴力 O(T*3*n) n为子串的长度 

最终 O(T*nlog(n)) n为母串加子串的长度

#include
#include
#include
#include
#include
#define ll long long
#define RG register
using namespace std;
const int maxn=210000;  //字符总长度加上连接字符的个数
int n;
int s[maxn],t1[maxn],t2[maxn],rk[maxn],c[maxn],height[maxn],sa[maxn],dp[maxn][19];
int cmp(int *r,int a,int b,int k)
{
    return r[a]==r[b]&&r[a+k]==r[b+k];
}
void build_sa(int n,int m)
{
    int *x=t1,*y=t2;
    for(int i=0;i=0;i--)sa[--c[x[i]]]=i;
    int p;
    for(int k=1;k<=n;k<<=1,m=p)
    {
        p=0;
        for(int i=n-k;i=k)y[p++]=sa[i]-k;
        for(int i=0;i=0;i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1;i=n)break;
    }
}
void getheight(int n)
{
    int k=0;
    for(int i=0;i

 

你可能感兴趣的:(后缀数组学习)