题链:

http://codevs.cn/problem/4158/

题解:

FFT。

定义两个相同长度的字符串s1,s2的距离为

$$dis(s1,s2)=\sum_{i=0}^{len-1}(s1[i]-s2[i])^2s1[i]s2[i]$$

如果两个字符串相同,那么dis=0。

(对于本题而言,只需把通配符用0表示,其它字符c用c-'a'+1表示。)

然后看看如何求出文本串T(长度为n)和模式串S(长度为m)的总共匹配数。

定义T串从$l$位置开始的长度为m的子串和S的距离为$D(l)$,那么:

$$D(l)=\sum_{k=0}^{m-1}(T[l+k]-S[k])^2T[l+k]S[k]$$

为了构成卷积形式,我们把S串翻转,即

$$D(l)=D'(l+m-1)=\sum_{k=0}^{m-1}(T[l+k]-S[m-1-k])^2T[l+k]S[m-1-k]$$

然而这个仍然不是卷积形式,我们再继续化一下式子:(令D(l)=D'(l+m-1))

$$\begin{aligned}
D'(l+m-1)&=\sum_{k=0}^{m-1}(T[l+k]-S[m-1-k])^2T[l+k]S[m-1-k]\\
&=\sum_{k=0}^{m-1}(T[l+k]^3S[m-1-k]-2T[l+k]^2S[m-1-k]^2+T[l+k]S[m-1-k]^3)\\
&=\sum_{k=0}^{m-1}T[l+k]^3S[m-1-k]+\sum_{k=0}^{m-1}-2T[l+k]^2S[m-1-k]^2+\sum_{k=0}^{m-1}T[l+k]S[m-1-k]^3
\end{aligned}$$

然后逮着这个式子做3组卷积即可。

代码:

#include<bits/stdc++.h>
#define MAXN 1048577
#define INF 0x3f3f3f3f
using namespace std;
const double Pi=acos(-1),eps=1e-6;
typedef complex<double>Complex;
Complex null(0,0);
int A[MAXN],B[MAXN],order[MAXN];
int idx(char ch){
if(ch=='*') return 0;
return ch-'a'+1;
}
void getstring(int *s,int len){
static char ch;
for(int i=0;i<len;i++)
scanf(" %c",&ch),s[i]=idx(ch);
}
void FFT(Complex *Y,int n,int sign){
for(int i=1;i<n;i++) if(i<order[i]) swap(Y[i],Y[order[i]]);
for(int d=2;d<=n;d<<=1){
Complex dw(cos(2*Pi/d),sin(sign*2*Pi/d)),w,tmp;
for(int i=0;w=Complex(1,0),i<n;i+=d)
for(int k=i;k<i+d/2;w=w*dw,k++)
tmp=w*Y[k+d/2],Y[k+d/2]=Y[k]-tmp,Y[k]=Y[k]+tmp;
}
}
int main(){
static int pos[MAXN];
static Complex f1[MAXN],g1[MAXN],f2[MAXN],g2[MAXN],f3[MAXN],g3[MAXN],D[MAXN];
int n,m,N,len,ans=0; scanf("%d%d",&n,&m);
getstring(A,n); getstring(B,m); reverse(A,A+n);
for(N=1,len=0;N<n+m-1;N<<=1) len++;
for(int i=1;i<N;i++) order[i]=(order[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0;i<n;i++){
f1[i]=Complex(A[i]*A[i]*A[i],0);
f2[i]=Complex(A[i]*A[i],0);
f3[i]=Complex(A[i],0);
}
for(int i=0;i<m;i++){
g1[i]=Complex(B[i],0);
g2[i]=Complex(B[i]*B[i],0);
g3[i]=Complex(B[i]*B[i]*B[i],0);
}
FFT(f1,N,1); FFT(g1,N,1);
FFT(f2,N,1); FFT(g2,N,1);
FFT(f3,N,1); FFT(g3,N,1);
for(int i=0;i<N;i++) D[i]=f1[i]*g1[i]-2.0*f2[i]*g2[i]+f3[i]*g3[i];
FFT(D,N,-1);
for(int i=0;i<m-n+1;i++)
if((int)((D[i+n-1].real()+0.5)/N)==0) pos[++ans]=i+1;
printf("%d\n",ans);
for(int i=1;i<=ans;i++) printf("%d ",pos[i]);
printf("\n");
return 0;
}

  

●Codevs 4158 残缺的字符串的更多相关文章

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

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

  2. 【BZOJ4259】残缺的字符串

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

  3. 【BZOJ4259】残缺的字符串(FFT)

    [BZOJ4259]残缺的字符串(FFT) 题面 给定两个字符串\(|S|,|T|\),两个字符串中都带有通配符. 回答\(T\)在\(S\)中出现的次数. \(|T|,|S|<=300000\ ...

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

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

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

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

  6. luoguP4173 残缺的字符串 FFT

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

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

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

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

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

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

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

随机推荐

  1. 20162327WJH程序设计与数据结构第七周总结

    学号 20162327 <程序设计与数据结构>第7周学习总结 教材学习内容总结 1.关于接口的理解:接口可以理解为比较纯粹的抽象类 2.接口的特点:用interface定义接口 接口中的方 ...

  2. Flask 视图

    写个验证用户登录的装饰器:在调用函数前,先检查session里有没有用户 from functools import wraps from flask import session, abort de ...

  3. Flask学习 三 web表单

    web表单 pip install flask-wtf 实现csrf保护 app.config['SECRET_KEY']='hard to guess string' # 可以用来存储框架,扩展,程 ...

  4. HTTP协议中PUT和POST使用区别

          有的观点认为,应该用POST来创建一个资源,用PUT来更新一个资源:有的观点认为,应该用PUT来创建一个资源,用POST来更新一个资源:还有的观点认为可以用PUT和POST中任何一个来做创 ...

  5. javascript递归函数

    递归函数:是指函数直接或间接调用函数本身,则称该函数为递归函数. 这句话理解起来并不难,从概念上出发,给出以下的例子: function foo(){ console.log("函数 foo ...

  6. 剑指offer-数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  7. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

  8. python中 return 的用法

    return 语句就是讲结果返回到调用的地方,并把程序的控制权一起返回 程序运行到所遇到的第一个return即返回(退出def块),不会再运行第二个return. 要返回两个数值,写成一行即可: de ...

  9. 返回到前台的String出现乱码问题

    使用springmvc给前天返回String类型的数据出现乱码问题可以在配置环境Spring-mvc.xml中添加如下代码 <mvc:annotation-driven> <mvc: ...

  10. Linux CentOS7.0 (01)在Vmvare Workstation上 安装配置

    一.新建虚拟机 1.创建新的虚拟机 -> 默认典型 ->选择安装介质 2.指定虚拟机名称.安装目录.磁盘容量大小 点击 "完成",创建虚拟机! 随后虚拟机将自动启动安装 ...