题目链接

题意分析

啥 ? ? ? \(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++

P4173 残缺的字符串的更多相关文章

  1. 洛谷 P4173 残缺的字符串 (FFT)

    题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...

  2. Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用

    P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...

  3. P4173 残缺的字符串(FFT字符串匹配)

    P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...

  4. P4173 残缺的字符串 fft

    题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...

  5. 洛谷P4173 残缺的字符串(FFT)

    传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...

  6. 洛谷P4173 残缺的字符串

    题目大意: 两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置 字符串长度\(\le 300000\) 考虑魔改一发\(kmp\),发现魔改不出来 于是考虑上网搜题解 然后考虑\ ...

  7. [Luogu P4173]残缺的字符串 ( 数论 FFT)

    题面 传送门:洛咕 Solution 这题我写得脑壳疼,我好菜啊 好吧,我们来说正题. 这题.....emmmmmmm 显然KMP类的字符串神仙算法在这里没法用了. 那咋搞啊(或者说这题和数学有半毛钱 ...

  8. luogu P4173 残缺的字符串

    传送门 两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是\(*\)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m 然而上面那个做法在字符集大 ...

  9. 洛谷 P4173 残缺的字符串

    (不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...

随机推荐

  1. java的内部编码

    java运行时,内存中使用的字符编码是unicode. 在编译java程序时,若我们不指定源程序文件的编码格式,JDK首先获得操作系统的file.encoding参数(它保存的就是操作系统默认的编码格 ...

  2. linux操作系统下,怎么使用kill按照PID一次杀死多个进程

    1.ps -ef | grep firefox | grep -v grep | cut -c 9-15 | xargs kill -s 9 说明:“grep firefox”的输出结果是,所有含有关 ...

  3. c/c++笔试面试试题

    C 试题(纯属转载) 1.求下面函数的返回值(微软) int func(x) {     int countx = 0;     while(x)     {           countx ++; ...

  4. dll详解

    [转]http://www.cnblogs.com/xuemaxiongfeng/articles/2461632.html 不解为什么要用WINAPI宏定义,查了后发现下面的定义.于是乎需要区别 _ ...

  5. p1429 平面最近点对(加强版)

    传送门 分析 我们可以枚举每一个点算它的最近点 估价函数应该分为3种情况计算: 大于max,小于min,位于min和max之间 代码 #include<iostream> #include ...

  6. easyui 获取当前页签选中的名称

    parent.parent.$("#tabs").tabs('getSelected').panel('options').title == "收藏夹管理"

  7. (转)Linux下安装Android的adb驱动-解决不能识别的问题(国产板子)

    注:本文不涉及怎么安装adb等工具.本方法通用.到目前为止已经解决rk3188和展讯SC6820(波导T9500)的识别问题. 以前调试的Android板子,都是直接用的Google的usb设备id, ...

  8. eclipse 按装lombok与注解说明

    原文:http://www.cnblogs.com/ywqbj/p/5711691.html 一.安装lombok 1.下载   lombok-1.16.16.jar 包 我的下载完后放到:/root ...

  9. JVM指令集(指令码、助记符、功能描述)

    JVM指令集(指令码.助记符.功能描述) 指令码 助记符 功能描述 0x00 nop 无操作 0x01 aconst_null 指令格式:  aconst_null 功能描述:  null进栈. 指令 ...

  10. Discuz!X2截屏控件手动安装教程-Xproer.ScreenCapture

    版权所有 2009-2015 荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com 官方博客:http://www.cnblogs.com/xproer 产品首页:h ...