P4173 残缺的字符串

题目链接

题意分析

啥 ? ? ? \(FFT\)做字符串匹配

可是就是这样

我们定义匹配函数

我们定义\(A\)是匹配串 \(B\)是被匹配串

我们当前到达\(B\)串的\(x\)位置

\[P(x)=\sum_{i=0}^{m-1}[A(i)-B(x-m+i+1)]\]

那么如果\(P(x)=0\)的话 是不是就是匹配上了呢? ?

不是 如果匹配的是\(ab\)以及\(ba\)的话 那么就\(WA\)

所以我们令

\[P(x)=\sum_{i=0}^{m-1}[A(i)-B(x-m+i+1)]^2\]

\[=\sum_{i=0}^{m-1}A^2(i)+\sum_{i=0}^{m-1}B^2(x-m+i+1)-2*\sum_{i=0}^{m-1}A(i)B(x-m+i+1)\]

我们如果颠倒一下就是 \(S(m-i-1)=S(i)\)

\[P(x)=\sum_{i=0}^{m-1}S^2(m-i+1)+\sum_{i=0}^{m-1}B^2(x-m+i+1)-2*\sum_{i=0}^{m-1}S(m-i-1)B(x-m+i+1)\]

首先第一项我们可以作为常量处理

第二项我们可以使用前缀和处理

第三项就是

\[\sum_{i+j=x}S(i)B(j)\]

我们可以使用\(FFT\)来做

如果加上了通配符呢 ? ? ?

我们就改良匹配公式

\[P(x)=\sum_{i=0}^{m-1}[A(i)-B(x-m+i+1)]^2A(i)B(x-m+i+1)\]

然后就是暴力展开

\[P(x)=\sum_{i=0}^{m-1}S^3(m-i-1)B(x-m+i+1)+\sum_{i=0}^{m-1}S(m-i-1)B^3(x-m+i+1)-2*\sum_{i=0}^{m-1}S^2(m-i-1)B(x-m+i+1)\]

我们弄成卷积的形式

\[P(x)=\sum_{i+j=x}S^3(i)B(j)+\sum_{i+j=x}S(i)B^3(j)-2*\sum_{i+j=x}S^2(i)B^2(j)\]

然后还是跑\(FFT\)

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#define IL inline
#define M 2008611
#define D double
#define eps 0.5
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
    T __=0,___=1;char ____=getchar();
    while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
    while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
    _=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
const D Pi=acos(-1.0);
int n,m,lim,all,top;D tot;
char s1[M],s2[M];
D sx[M],sy[M];int key[M],sta[M];
struct Node{
    D xx,yy;
    Node(D xxx=0,D yyy=0){xx=xxx;yy=yyy;}
    friend Node operator +(const Node &A,const Node &B)
    {return (Node){A.xx+B.xx,A.yy+B.yy};}
    friend Node operator -(const Node &A,const Node &B)
    {return (Node){A.xx-B.xx,A.yy-B.yy};}
    friend Node operator *(const Node &A,const Node &B)
    {return (Node){A.xx*B.xx-A.yy*B.yy,A.xx*B.yy+A.yy*B.xx};}
    friend Node operator /(const Node &A,const D &B)
    {return (Node){A.xx/B,A.yy/B};}
    friend Node operator *(const Node &A,const D &B)
    {return (Node){A.xx*B,A.yy*B};}
}cdy[M],wzy[M],ans[M];
IL void FFT(Node *A,int knd)
{
    for(R int i=0;i<lim;++i) if(i<key[i]) swap(A[i],A[key[i]]);
    for(R int mid=1;mid<lim;mid<<=1)
    {
        Node Wn=(Node){cos(Pi/mid),knd*sin(Pi/mid)};
        for(R int j=0;j<lim;j+=(mid<<1))
        {
            Node w=(Node){1,0};
            for(R int k=0;k<mid;++k,w=w*Wn)
            {
                Node x=A[j+k],y=w*A[j+k+mid];
                A[j+k]=x+y;A[j+k+mid]=x-y;
            }
        }
    }
    if(knd==-1)
    for(R int i=0;i<lim;++i)
    A[i]=A[i]/lim;
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n);read(m);scanf("%s%s",s1,s2);
    for(lim=1;lim<(m<<1);lim<<=1) ++all;
    for(R int i=0;i<lim;++i) key[i]=((key[i>>1]>>1)|((i&1)<<(all-1)));
    for(R int i=0;i<n;++i) if(s1[i]!='*') sx[i]=(s1[i]-'a'+1);
    for(R int i=0;i<m;++i) if(s2[i]!='*') sy[i]=(s2[i]-'a'+1);
    reverse(sx,sx+n);
    for(R int i=0;i<n;++i) cdy[i]=(Node){sx[i]*sx[i]*sx[i],0};
    for(R int i=0;i<m;++i) wzy[i]=(Node){sy[i],0};
    FFT(cdy,1);FFT(wzy,1);
    for(R int i=0;i<lim;++i) ans[i]=ans[i]+cdy[i]*wzy[i];
//  for(R int i=0;i<lim;++i) printf("%.4f\n",ans[i].xx);
    
    for(R int i=0;i<lim;++i) cdy[i]=wzy[i]=(Node){0,0};
    for(R int i=0;i<n;++i) cdy[i]=(Node){sx[i]*sx[i],0};
    for(R int i=0;i<m;++i) wzy[i]=(Node){sy[i]*sy[i],0};
    FFT(cdy,1);FFT(wzy,1);
    for(R int i=0;i<lim;++i) ans[i]=ans[i]-cdy[i]*wzy[i]*2.0;
//  for(R int i=0;i<lim;++i) printf("%.4f\n",ans[i].xx);
    
    for(R int i=0;i<lim;++i) cdy[i]=wzy[i]=(Node){0,0};
    for(R int i=0;i<n;++i) cdy[i]=(Node){sx[i],0};
    for(R int i=0;i<m;++i) wzy[i]=(Node){sy[i]*sy[i]*sy[i],0};
    FFT(cdy,1);FFT(wzy,1);
    for(R int i=0;i<lim;++i) ans[i]=ans[i]+cdy[i]*wzy[i];
//  for(R int i=0;i<lim;++i) printf("%.4f\n",ans[i].xx);        
    FFT(ans,-1);
//  for(R int i=0;i<lim;++i) printf("%.4f\n",ans[i].xx);
    
    for(R int i=n-1;i<m;++i)
    if(fabs(ans[i].xx)<eps) sta[++top]=i-n+2;
    printf("%d\n",top);
    for(R int i=1;i<=top;++i)
    printf("%d%c",sta[i],(i==top ? '\n':' '));
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

HEOI 2019 RP++

转载于:https://www.cnblogs.com/LovToLZX/p/10590543.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值