真实脑洞题

因为通配符所以导致t串实际有指数级别个,任何字符串相关算法都没有用

考虑一个新的匹配方法:设a串(模板串)长为n,从m串的i位置开始匹配:\( \sum_{i=0}{n-1}(a[j]-b[i+j])2a[j] \)

这个东西只有在从i开始的长为n的a串子串与b串完全匹配的时候才为0,因为首先如果两个字符相同,差的平方和才为0,令t中的'?'值为0,这样某一位为0就是这一位的字符匹配上或者a串的这一位通配

然后考虑优化这个n^2的东西

\[c[i]=\sum_{i=0}^{n-1}(a[j]-b[i+j])^2a[j]
\]

\[=\sum_{i=0}^{n-1}a[j]^3+a[j]b[i+j]^2-2a[j]^2b[i+j]
\]

\[=\sum_{i=0}^{n-1}a[j]^3+\sum_{i=0}^{n-1}a[j]b[i+j]^2-2\sum_{i=0}^{n-1}a[j]^2b[i+j]
\]

前面的是常数,所以我们只需要考虑快速计算形如\( \sum_{i=0}^{n-1}a[j]b[i+j] \) 的东西即可,设na nb分别是a b数组倒过来(也就是reverse一下)

\[\sum_{i=0}^{n-1}a[j]b[i+j]
\]

\[=\sum_{i=0}^{n-i-1}a[j]b[i+j]+\sum_{i=n-i}^{n-1}a[j]b[i+j]
\]

\[=\sum_{i=0}^{n-i-1}a[j]nb[n-i-1-j]+\sum_{i=0}^{i-1}a[n-i+j]b[n+j]
\]

\[=\sum_{i=0}^{n-i-1}a[j]nb[(n-i-1)-j]+\sum_{i=0}^{i-1}na[(i-1)-j]b[n+j]
\]

这样就两部分卷积可以用FFT优化了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=500005;
int n,m,bt,lm,re[N],tot;
double ans[N],sm;
char s[N],t[N];
struct cd
{
double a,b;
cd(double A=0,double B=0)
{
a=A,b=B;
}
cd operator + (const cd &x) const
{
return cd(a+x.a,b+x.b);
}
cd operator - (const cd &x) const
{
return cd(a-x.a,b-x.b);
}
cd operator * (const cd &x) const
{
return cd(a*x.a-b*x.b,a*x.b+b*x.a);
}
}a[N],b[N],a2[N],b2[N],na[N],nb[N],na2[N],nb2[N];
void dft(cd a[],int f)
{
for(int i=0;i<lm;i++)
if(i<re[i])
swap(a[i],a[re[i]]);
for(int i=1;i<lm;i<<=1)
{
cd wi=cd(cos(M_PI/i),f*sin(M_PI/i));
for(int k=0;k<lm;k+=(i<<1))
{
cd w=cd(1,0),x,y;
for(int j=0;j<i;j++)
{
x=a[j+k],y=w*a[i+j+k];
a[j+k]=x+y,a[i+j+k]=x-y;
w=w*wi;
}
}
}
if(f==-1)
for(int i=0;i<lm;i++)
a[i].a/=lm;
}
void fft(cd a[],cd b[])
{
dft(a,1);
dft(b,1);
for(int i=0;i<lm;i++)
a[i]=a[i]*b[i];
dft(a,-1);
}
int main()
{
scanf("%s%s",s,t);
m=strlen(s),n=strlen(t);
for(int i=0;i<n;i++)
a[i].a=(t[i]=='?')?0:t[i]-'a'+1,a2[i].a=a[i].a*a[i].a,sm+=a[i].a*a[i].a*a[i].a;
for(int i=0;i<m;i++)
b[i].a=s[i]-'a'+1,b2[i].a=b[i].a*b[i].a;
for(int i=0;i<m;i++)
na[i]=a[m-i-1],nb[i]=b[m-i-1],na2[i]=a2[m-i-1],nb2[i]=b2[m-i-1];
for(bt=0;(1<<bt)<=2*m;bt++);
lm=1<<bt;
for(int i=0;i<lm;i++)
re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
fft(a,nb2);
fft(b2,na);
fft(a2,nb);
fft(b,na2);
for(int i=0;i<=m-n;i++)
{
ans[i]=sm+(int)(a[m-i-1].a+0.5)-2*(int)(a2[m-i-1].a+0.5);
if(i>0)
ans[i]+=(int)(b2[i-1].a+0.5)-2*(int)(b[i-1].a+0.5);
tot+=(ans[i]==0);
}
printf("%d\n",tot);
for(int i=0;i<=m-n;i++)
if(ans[i]==0)
printf("%d ",i);
return 0;
}

bzoj 4503: 两个串【脑洞+FFT】的更多相关文章

  1. BZOJ 4503 两个串(FFT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4503 [题目大意] 给出S串和T串,计算T在S中出现次数,T中有通配符'?'. [题解 ...

  2. BZOJ 4503: 两个串 [FFT]

    4503: 两个串 题意:兔子们在玩两个串的游戏.给定两个只含小写字母的字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有"?"字符,这个字符可以匹 ...

  3. 【BZOJ 4503】4503: 两个串 (FFT)

    4503: 两个串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 497  Solved: 226 Description 兔子们在玩两个串的游戏.给 ...

  4. BZOJ.4503.两个串(FFT/bitset)

    题目链接 \(Description\) 给定两个字符串S和T,求T在S中出现了几次,以及分别在哪些位置出现.T中可能有'?'字符,这个字符可以匹配任何字符. \(|S|,|T|\leq 10^5\) ...

  5. bzoj 4503 两个串

    Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字符. Input 两行两个字 ...

  6. 【刷题】BZOJ 4503 两个串

    Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有"?"字符,这个字符可以匹配任何字符. I ...

  7. bzoj 4503 两个串 快速傅里叶变换FFT

    题目大意: 给定两个\((length \leq 10^5)\)的字符串,问第二个串在第一个串中出现了多少次.并且第二个串中含有单字符通配符. 题解: 首先我们从kmp的角度去考虑 这道题从字符串数据 ...

  8. bzoj 4503 两个串——FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 翻转T,就变成卷积.要想想怎么判断. 因为卷积是乘积求和,又想到相等的话相减为0,所以 ...

  9. bzoj 4503 两个串 —— FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 推式子即可: 不知怎的调了那么久,应该是很清晰的. 代码如下: #include< ...

随机推荐

  1. Oracle递归查询的原理

    在Oracle 10g下.来到scott用户下.分别以层次 1,2,3,4上的节点做实验: 当start with是根节点(level=1),要查其子节点,connect by pump和emp都是被 ...

  2. ajax的异步操作及页面重定向跳转

    今天主要分享一个简单的ajax的异步操作数据,用javascript也有一段时间了,刚开始看到一些页面在没有页面刷新的情况下就可以实现数据的保存或者获取,觉得挺不可思议的,感觉速度很快,做了几个项目之 ...

  3. Android IntentService的使用和源代码分析

    引言 Service服务是Android四大组件之中的一个,在Android中有着举足重轻的作用.Service服务是工作的UI线程中,当你的应用须要下载一个文件或者播放音乐等长期处于后台工作而有没有 ...

  4. iOS 开发常用的调试工具

    前言 最近博主临近毕业季,为了完美的写一篇毕业论文,真是:“锄禾日当午,汗滴禾下土”<—— 这句诗跟毕业我写毕业论文没任何一毛钱关系,我就是突然想吟湿了.不过博主作为网络工程专业的好青年,曾经的 ...

  5. oracle服务丢失的处理方法之OracleServiceORCL不存在示例

    oracle服务是oracle数据库的重要组成部分,下面就教您oracle服务丢失的处理方法,如果您之前遇到过oracle服务丢失的问题,不妨一看. 今天发现数据库服务器上的所有oracle服务都丢失 ...

  6. ERROR: cannot start Android Studio. No JDK found. Please validate either ANDROID_STUDIO_JDK, JDK_HOME + Unrecognized VM option '+UseCodeCacheFlushing

    想学下android,在本来想用myeclipse安装下sdk和adt,谁知在官网看到http://developer.android.com/sdk/index.html Google I/O 20 ...

  7. HTTP服务器用什么组件或者方式比较好

    我目前用Indy的HttpServer组件来编写,但遇到一个暂时没有办法解决的问题,就是上传文件到这个HTTPServer,如果文件名包含中文,则会出现乱码.网上查了一下,这是个indy的遗留问题,据 ...

  8. 织梦文章页调用当前栏目名称和url地址的方法

    其实织梦本身有这2个调用标签,可能大家没怎么注意,下面的代码就是织梦文章页调用当前栏目名称和url地址的方法: {dede:field name='typeurl' function=”GetType ...

  9. Java中的Lock

    同步机制是Java并发编程中最重要的机制之一,锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能防止多个线程同时访问共享资源(但是也有例外,比如读写锁).Java中可以使用synchroniz ...

  10. JavaScript实现Map、Reduce和Filter

    1. [代码][JavaScript]代码     <script type="text/javascript">// 函数式编程:// 描述我们要做什么,而不是我们如 ...