[Luogu4173/BZOJ4259] 残缺的字符串

17人阅读 评论(0) 收藏 举报
分类:

题目描述:

给出一个模板串和一个母串,问模板串在母串中出现过几次。带通配符。

题目分析:

设F[i]表示把模板串是否能够与母串的第[is+1i]形成的串匹配.
f[i]/g[i]表示两个串的数值,当为’*’的时候,值为0,否则为与’a’的差值+1
F[i]=j=0s1f(ij)g(i)(f(ij)g(i))
显然,当模板串能够与母串的第[is+1i]形成的串匹配.
F[i]==0
F[i]=f[ij]3g[j]2f[ij]2g[j]2+f[ij]g[j]3
每一项都是一个卷积的形式,做3次FFT就行了

题目链接:

Luogu 4173
BZOJ 权限题目

Ac 代码:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
const int maxm=300010*4;
const double PI=std::acos(-1);
struct complex{
    double real,imag;
    complex(){};
    complex(double _real,double _imag):real(_real),imag(_imag){}
}; 
inline complex operator + (complex x,complex y){return (complex){x.real+y.real,x.imag+y.imag};}
inline complex operator - (complex x,complex y){return (complex){x.real-y.real,x.imag-y.imag};}
inline complex operator * (complex x,complex y){return (complex){x.real*y.real-x.imag*y.imag,x.real*y.imag+y.real*x.imag};}
int len,rev[maxm];
complex A[maxm],B[maxm];
inline void FFT(complex *a,int n,int f)
{
    for(int i=0;i<n;i++) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1)
    {
        complex wn=(complex){std::cos(PI/i),f*std::sin(PI/i)};
        for(int j=0;j<n;j+=(i<<1))
        {
            complex w=(complex){1,0};
            for(int k=0;k<i;k++,w=w*wn)
            {
                complex x=a[j+k];
                complex y=a[i+j+k]*w;
                a[j+k]=x+y;
                a[i+j+k]=x-y;
            }
        }
    }
    if(f==1) return;
    for(int i=0;i<n;i++) a[i].real=a[i].real/n;
}
inline void init(int n)
{
    for(int i=0;i<n;i++) A[i]=(complex){0,0},B[i]=(complex){0,0};
}
double f[maxm],g[maxm];
char s[maxm],t[maxm];
ll F[maxm];
int n,m,S,T;
int ans[maxm],tot;
int main()
{
    scanf("%d%d",&S,&T);
    scanf("%s%s",s,t);
    for(int i=0;i<S/2;i++) std::swap(s[i],s[S-i-1]);
    for(int i=0;i<T;i++) f[i]=(t[i]=='*'?0:(t[i]-'a'+1.0));
    for(int i=0;i<S;i++) g[i]=(s[i]=='*'?0:(s[i]-'a'+1.0));
    m=S+T-2;
    for(n=1;n<=m;n<<=1) len++;
    for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
    init(n);
    for(int i=0;i<T;i++) A[i].real=f[i]*f[i]*f[i];
    for(int i=0;i<S;i++) B[i].real=g[i];
    FFT(A,n,1),FFT(B,n,1);
    for(int i=0;i<n;i++) A[i]=A[i]*B[i];
    FFT(A,n,-1);
    for(int i=0;i<T;i++) F[i]=(ll)round(A[i].real);
    init(n);
    for(int i=0;i<T;i++) A[i].real=(f[i]*f[i]);
    for(int i=0;i<S;i++) B[i].real=(g[i]*g[i]); 
    FFT(A,n,1),FFT(B,n,1);
    for(int i=0;i<n;i++) A[i]=A[i]*B[i];
    FFT(A,n,-1);
    for(int i=0;i<T;i++) F[i]-=2ll*round(A[i].real);
    init(n);
    for(int i=0;i<T;i++) A[i].real=(f[i]);
    for(int i=0;i<S;i++) B[i].real=(g[i]*g[i]*g[i]); 
    FFT(A,n,1),FFT(B,n,1);
    for(int i=0;i<n;i++) A[i]=A[i]*B[i];
    FFT(A,n,-1);
    for(int i=0;i<T;i++) F[i]+=(ll)round(A[i].real);
    for(int i=S-1;i<T;i++) if(!F[i]) ans[++tot]=i-S+2;
    printf("%d\n",tot);
    for(int i=1;i<=tot;i++) printf("%d ",ans[i]);
    return 0;
}
查看评论

bzoj 4259: 残缺的字符串 (FFT)

题目描述传送门题目大意:给出两个带通配符的字符串,求匹配的个数。题解FFT裸题,通配符的位置赋值成0 f[i]=∑j=1n(g[j]−h[i−j])2∗g[j]∗h[i−j]f[i]=\sum\li...
  • clover_hxy
  • clover_hxy
  • 2017年03月17日 09:58
  • 263

[BZOJ4259] 残缺的字符串 (FFT)

题意:定义*号可匹配任意字符。给出A串,B串,求A串在B中完全匹配的所有位置。 将*号视作0,则两个等长的串可匹配当且仅当Σ(a[i]-b[i])^2*a[i]*b[i]==0。将A串和B串最左边对...
  • u011542204
  • u011542204
  • 2016年02月21日 17:42
  • 1394

[BZOJ4259]残缺的字符串(FFT)

题目描述传送门题目大意:给出一个模板串和一个母串,问模板串在母串中出现过几次。带通配符。题解这道题和两个串那道题是差不多的。。 令F(i)表示将模板串的最后一个怼到母串的第i个是否能匹配,0表示能匹...
  • Clove_unique
  • Clove_unique
  • 2017年04月24日 10:40
  • 430

bzoj4259: 残缺的字符串

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4259 思路:FFT是一种高效的字符串匹配算法 只要想到FFT就好办了 令为‘*’的位置...
  • thy_asdf
  • thy_asdf
  • 2016年07月01日 11:56
  • 380

[BZOJ4259]残缺的字符串

题目大意给定模板串AA和母串BB,长度分别为mm和nn,你需要统计模板串在母串中所有出现的位置。 字符集都是小写拉丁字母,而且存在通配符∗*能够匹配任意字符。1≤m,n≤3×1051\le m,n\...
  • a_crazy_czy
  • a_crazy_czy
  • 2017年04月22日 22:06
  • 264

BZOJ4259: 残缺的字符串

一直在想各种字符串匹配算法… 将’a’视为1,’b’视为2,‘*’视为0 那么A0......AnA0......AnA_0......A_n和Bk.....Bk+n−1Bk.....Bk+n−1...
  • L_0_Forever_LF
  • L_0_Forever_LF
  • 2018年03月05日 16:55
  • 48

[BZOJ4259][FFT]残缺的字符串

复习一下FFT http://blog.csdn.net/u011542204/article/details/50708834 感觉这种字符串匹配的方法很棒啊 然而我的代码被卡常卡内存……#i...
  • Coldef
  • Coldef
  • 2017年04月10日 14:33
  • 207

[BZOJ4259] 残缺的字符串 FFT

如果我们把*看成00,两个串相等当且仅当∑AiBi(Ai−Bi)2=0\sum A_iB_i(A_i-B_i)^2=0。 答案要求的就是对于每个tt,∑AiBi+t(Ai−Bi+t)2\sum A_...
  • DOFYPXY
  • DOFYPXY
  • 2018年01月04日 21:58
  • 105

bzoj4259 残缺的字符串(dp+FFT)

Description很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程...
  • wu_tongtong
  • wu_tongtong
  • 2018年03月01日 17:04
  • 28

【BZOJ4259】残缺的字符串-FFT

测试地址:残缺的字符串 题目大意:给定两个带通配符的字符串A,BA,BA,B,问AAA在BBB中能匹配的所有位置。 做法:本题需要用到FFT。 这题看上去是一个字符串题,然而KMP算法在带通配符...
  • Maxwei_wzj
  • Maxwei_wzj
  • 2018年04月01日 10:13
  • 16
    个人资料
    持之以恒
    等级:
    访问量: 6万+
    积分: 7015
    排名: 4144
    文章分类
    最新评论