[bzoj4503]两个串
来源:互联网 发布:储罐设计软件 编辑:程序博客网 时间:2024/06/05 17:06
题目大意
兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,
分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。
FFT
我们把T串反过来。
设a表示S串(把字符转成不为0的数字)
b表示T串,其中问号可以用一个0表示
设
容易证明S串的第j个位置为开头能匹配T串则c[j+m-1]=0。
而右边的含义就是T的第i能否匹配S的第j+i。
由于贡献一定非负,最终为0一定是每一项均为0,也就是匹配成功。
后面的拆一下可以做三次FFT完成。
#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef double db;const db pi=acos(-1);const int maxn=530000+10;struct node{ db x,y; friend node operator +(node a,node b){ node c; c.x=a.x+b.x;c.y=a.y+b.y; return c; } friend node operator -(node a,node b){ node c; c.x=a.x-b.x;c.y=a.y-b.y; return c; } friend node operator *(node a,node b){ node c; c.x=a.x*b.x-a.y*b.y;c.y=a.x*b.y+a.y*b.x; return c; }};node a[maxn],b[maxn],c[maxn],d[maxn],e[maxn],f[maxn],tt[maxn],w[maxn];int rev[maxn],ans[maxn];db ce;char s[maxn],h[maxn];int i,j,k,l,t,n,m,mx,len,top;int pow(int x,int y){ if (y==2) return x*x; else return x*x*x;}void prepare(){ w[0].x=1;w[0].y=0; w[1].x=cos(2*pi/len);w[1].y=sin(2*pi/len); fo(i,2,len) w[i]=w[i-1]*w[1]; fo(i,0,len-1){ int p=0; for (int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2); rev[i]=p; }}void DFT(node *a,int sig){ int i; fo(i,0,len-1) tt[rev[i]]=a[i]; for (int m=2;m<=len;m*=2){ int half=m/2,bei=len/m; fo(i,0,half-1){ node wi=sig>0?w[i*bei]:w[len-i*bei]; for (int j=i;j<len;j+=m){ node u=tt[j],v=tt[j+half]*wi; tt[j]=u+v; tt[j+half]=u-v; } } } if (sig==-1) fo(i,0,len-1) tt[i].x/=len; fo(i,0,len-1) a[i]=tt[i];}void FFT(node *a,node *b,node *c){ int i; fo(i,0,len-1) e[i]=a[i],f[i]=b[i]; DFT(e,1);DFT(f,1); fo(i,0,len-1) e[i]=e[i]*f[i]; DFT(e,-1); fo(i,0,len-1) c[i]=e[i];}int main(){ //freopen("4503.in","r",stdin); scanf("%s",s); n=strlen(s); scanf("%s",h); m=strlen(h); mx=max(n,m); len=1; while (len<mx*2) len*=2; ce=log(len)/log(2); prepare(); reverse(h,h+m); fo(i,0,n-1) a[i].x=pow(s[i]-'a'+1,3); fo(i,0,m-1) b[i].x=(h[i]=='?'?0:h[i]-'a'+1); FFT(a,b,d); fo(i,0,len-1) c[i]=c[i]+d[i]; fo(i,0,n-1) a[i].x=-2*pow(s[i]-'a'+1,2); fo(i,0,m-1) b[i].x=pow(h[i]=='?'?0:h[i]-'a'+1,2); FFT(a,b,d); fo(i,0,len-1) c[i]=c[i]+d[i]; fo(i,0,n-1) a[i].x=s[i]-'a'+1; fo(i,0,m-1) b[i].x=pow(h[i]=='?'?0:h[i]-'a'+1,3); FFT(a,b,d); fo(i,0,len-1) c[i]=c[i]+d[i]; fo(i,0,n-m) if (int(c[i+m-1].x)==0) ans[++top]=i; printf("%d\n",top); fo(i,1,top) printf("%d\n",ans[i]);}
0 0
- BZOJ4503 两个串
- [bzoj4503]两个串
- Bzoj4503 两个串 FFT
- bzoj4503 两个串
- [bzoj4503]两个串
- bzoj4503 两个串
- Bzoj4503:两个串:FFT,构造
- [BZOJ4503]两个串(FFT)
- bzoj4503两个串 快速傅里叶变换(FFT)
- [BZOJ4503]两个串(快速傅立叶变换FFT)
- [bzoj4503]&[caioj1455][FFT]串
- bzoj4503
- 两个串-----FFT妙用!
- 4503: 两个串 FFT
- 【BZOJ 4503】两个串
- BZOJ 4503 两个串
- BZOJ 4503: 两个串
- bzoj 4503 两个串
- SVN使用
- OpenGL Shader 1
- C++中list、deque以及vector对比
- 开源深度学习库BigDL在阿里云E-MapReduce上的实践
- 奇怪的分式
- [bzoj4503]两个串
- ios开发中故事板和代码之间的关系
- maven安装配置
- (java)leetcode-24
- JS面向对象-原型链的认知
- SVN和Git 介绍,区别,优缺点,适用范围总结
- AES/RSA加密开源库使用
- 讯飞开发遇到的坑----开发文档缺少一个依赖库
- 线程同步