传送门

fftfftfft套路题。

我们把aaa ~ zzz映射成111 ~ 262626,然后把∗*∗映射成000。

考虑对于两个长度都为nnn的字符串A,BA,BA,B。

我们定义一个差异函数dist(A,B)=∑i=1n(ai−bi)2aibidist(A,B)=\sum_{i=1}^n(a_i-b_i)^2a_ib_idist(A,B)=∑i=1n​(ai​−bi​)2ai​bi​其中a,ba,ba,b是A,BA,BA,B的字符的映射值。

然后如果dist(A,B)=0dist(A,B)=0dist(A,B)=0说明两个字符串可以匹配。

然后我们用000把原题中给出的第一个字符串的长度补成nnn,再翻转一下。

然后将两个序列卷积一下可以求出对于第二个串匹配起点在1,2,...n−m+11,2,...n-m+11,2,...n−m+1时分别的distdistdist值。

只需要看哪些位是000就行了。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const int N=2e6+5;
int tim=0,lim=1,n,m,A[N],B[N],pos[N];
ll sum[N];
vector<int>ans;
char s[N];
struct Complex{
    double x,y;
    inline Complex operator+(const Complex&b){return (Complex){x+b.x,y+b.y};}
    inline Complex operator-(const Complex&b){return (Complex){x-b.x,y-b.y};}
    inline Complex operator*(const Complex&b){return (Complex){x*b.x-y*b.y,y*b.x+b.y*x};}
    inline Complex operator/(const double&b){return (Complex){x/b,y/b};}
}a[N],b[N];
inline void fft(Complex *a,int type){
    for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
    for(ri mid=1;mid<lim;mid<<=1){
        Complex wn=(Complex){cos(pi/mid),type*sin(pi/mid)};
        for(ri j=0,len=mid<<1;j<lim;j+=len){
            Complex w=(Complex){1,0};
            for(ri k=0;k<mid;++k,w=w*wn){
                Complex a0=a[j+k],a1=w*a[j+k+mid];
                a[j+k]=a0+a1,a[j+k+mid]=a0-a1;
            }
        }
    }
    if(type==-1)for(ri i=0;i<lim;++i)a[i]=a[i]/lim;
}
inline void solve1(){
    for(ri i=0;i<=n;++i)a[i].x=A[i]*A[i]*A[i],b[i].x=B[i];
    fft(a,1),fft(b,1);
    for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
    fft(a,-1);
    for(ri i=0;i<lim;++i)sum[i]+=(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
inline void solve2(){
    for(ri i=0;i<=n;++i)a[i].x=A[i]*A[i],b[i].x=B[i]*B[i],a[i].y=b[i].y=0;
    fft(a,1),fft(b,1);
    for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
    fft(a,-1);
    for(ri i=0;i<lim;++i)sum[i]-=2ll*(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
inline void solve3(){
    for(ri i=0;i<=n;++i)a[i].x=A[i],b[i].x=B[i]*B[i]*B[i],a[i].y=b[i].y=0;
    fft(a,1),fft(b,1);
    for(ri i=0;i<lim;++i)a[i]=a[i]*b[i];
    fft(a,-1);
    for(ri i=0;i<lim;++i)sum[i]+=(ll)(a[i].x+0.5),a[i].x=a[i].y=b[i].x=b[i].y=0;
}
int main(){
	int ml;
    scanf("%d%d",&m,&n),ml=m+n,--m,--n;
    scanf("%s",s);
    for(ri i=0;i<=m;++i)A[i]=s[i]=='*'?0:s[i]-'a'+1;
    reverse(A,A+m+1);
    scanf("%s",s);
    for(ri i=0;i<=n;++i)B[i]=s[i]=='*'?0:s[i]-'a'+1;
    while(lim<=ml)lim<<=1,++tim;
    for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
    solve1(),solve2(),solve3();
    for(ri i=m,j=1;i<=n;++i,++j)if(!sum[i])ans.push_back(j);
    printf("%d\n",ans.size());
    for(ri i=0;i<ans.size();++i)printf("%d ",ans[i]);
    return 0;
}

2018.11.17 bzoj4259: 残缺的字符串(fft)的更多相关文章

  1. BZOJ4259:残缺的字符串(FFT)

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

  2. BZOJ4259: 残缺的字符串(FFT 字符串匹配)

    题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...

  3. International Programming Retreat Day(2018.11.17)

    时间:2018.11.17地点:北京国华投资大厦

  4. luoguP4173 残缺的字符串 FFT

    luoguP4173 残缺的字符串 FFT 链接 luogu 思路 和昨天做的题几乎一样. 匹配等价于(其实我更喜欢fft从0开始) \(\sum\limits_{i=0}^{m-1}(S[i+j]- ...

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

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

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

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

  7. 【BZOJ4259】残缺的字符串 FFT

    [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...

  8. BZOJ 4259: 残缺的字符串 [FFT]

    4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...

  9. CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串

    Fuzzy Search 给你文本串 S 和模式串 T,求 S 的每个位置是否能模糊匹配上 T. 这里的模糊匹配指的是把 T 放到 S 相应位置上之后,T 中每个字符所在位置附近 k 个之内的位置上的 ...

随机推荐

  1. POJ-2386.Lakecounting(DFS求连通块)

    本题是一道连通块的入门题,用来练手,后续还会更新连通块的题目. 本题大意:一个n * m 的陆地上面有很多水洼,让你统计水洼的个数并输出. 本题思路:按照顺序遍历陆地,如果发现水洼就将它的八连块都进行 ...

  2. jQuery之禁止Get请求缓存

    如果两次Get请求的URL完全一样,则IE浏览器会调用上次缓存的结果,不会发起新的Http请求. 解决办法:在URL最后面加上时间戳. jQuery全局设置禁止缓存 $.ajaxSetup({ cac ...

  3. express 学习札记

    Enjoy yourself! 祝你玩得开心! I have no idea. 我没有头绪. I just made it! 我做到了!  I’ll see to it 我会留意的. Express ...

  4. 微信小程序开发——开发者工具无法输入中文的处理

    问题模块 框架类型 问题类型 操作系统 工具版本 开发者工具 小程序 Bug Windows v.02.1810290 异常描述: 无法输入中文,偶现,但是概率有点高,重启,重装,更新版本等等都未解决 ...

  5. [剑指Offer]22-链表中倒数第k个结点

    题目链接 https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?tpId=13&tqId=11167&t ...

  6. mysql学习1:数据类型:数字型,日期和时间,字符串类型(总结)

    mysql数据类型:数字型,日期和时间,字符串类型 摘要 MySQL中定义数据字段的类型对数据库的优化是非常重要的: MySQL支持多种类型,大致可以分为三类,如下. 数字类型 整数:tinyint. ...

  7. MYSQL 优化常用方法总结

    1, 选取最合适的字段属性以及长度 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快. 比如:定义邮政编码 char(6) 最合适,如果char(2 ...

  8. RibbonControl 工具栏上的一些基本操作

    1:左上角图标的属性项 应用程序ico标 ribboncontrol默认 左上角图标区域隐藏,先转换成 ribbonFrom 然后区域出现 下一步修改此区域ico:右键ribbonControl1 属 ...

  9. js的RegExp

    正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的. 所以我们判断一个字符串 ...

  10. oracle 单表导出导入

    exp username/password@服务名 file=d:\daochu.dmp tables=(tableneme,...)