Description

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

Input

两行两个字符串,分别代表S和T

Output

第一行一个正整数k,表示T在S中出现了几次
接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。

Sample Input

ababcadaca
a?a

Sample Output

3
0
5

HINT

S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”
 
这种通配符匹配问题一般就是多项式乘法。
把T串倒过来,把a到z变成1到26,'?'变成0,设计一个函数F(x)=∑(A[i]-B[j])^2*A[i]*B[j],这样对于两个位置i,j,恰好满足题意(A[i]=A[j]或A[i]、B[j]中至少有一个?)。
拆一下F(x)=∑A[i]^3 * B[j] + B[j]^3 * A[i] - 2*A[i]*A[i] * B[j]*B[j]
三次NTT乘法。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int G=3;
const int p=998244353;
const int maxn=270010;
int pow(ll n,int m) {
ll ans=1;
for(;m;(n*=n)%=p,m>>=1) if(m&1) (ans*=n)%=p;
return ans;
}
int wn[20];
void NTT(int* A,int len,int tp) {
int j=len>>1,c=0;
rep(i,1,len-2) {
if(i<j) swap(A[i],A[j]);int k=len>>1;
while(j>=k) j-=k,k>>=1;j+=k;
}
for(int i=2;i<=len;i<<=1) {
c++;for(int j=0;j<len;j+=i) {
int w=1;
for(int k=j;k<j+(i>>1);k++) {
int u=A[k],t=(ll)A[k+(i>>1)]*w%p;
A[k]=(u+t)%p;A[k+(i>>1)]=(u-t+p)%p;
w=(ll)w*wn[c]%p;
}
}
}
if(tp<0) {
int inv=pow(len,p-2);
rep(i,1,len/2-1) swap(A[i],A[len-i]);
rep(i,0,len-1) A[i]=(ll)A[i]*inv%p;
}
}
char s[maxn],t[maxn];
int A[maxn],B[maxn],ans[maxn];
int main() {
rep(i,1,19) wn[i]=pow(G,(p-1)/(1<<i));
scanf("%s%s",s,t);
int n=strlen(s),m=strlen(t),len=1;while(len<(n<<1)||len<(m<<1)) len<<=1;
rep(i,0,n-1) s[i]-='a'-1;
rep(i,0,m-1) t[i]=((t[i]=='?')?0:t[i]-'a'+1);
//A[i]^3 * B[j]
rep(i,0,n-1) A[i]=s[i]*s[i]*s[i];
rep(i,0,m-1) B[m-i-1]=t[i];
NTT(A,len,1);NTT(B,len,1);
rep(i,0,len-1) A[i]=(ll)A[i]*B[i]%p;
NTT(A,len,-1);
rep(i,0,len-1) (ans[i]+=A[i])%=p;
//B[j]^3 * A[i]
memset(A,0,sizeof(A));memset(B,0,sizeof(B));
rep(i,0,n-1) A[i]=s[i];
rep(i,0,m-1) B[m-i-1]=t[i]*t[i]*t[i];
NTT(A,len,1);NTT(B,len,1);
rep(i,0,len-1) A[i]=(ll)A[i]*B[i]%p;
NTT(A,len,-1);
rep(i,0,len-1) (ans[i]+=A[i])%=p;
//- 2*A[i]*A[i] * B[j]*B[j]
memset(A,0,sizeof(A));memset(B,0,sizeof(B));
rep(i,0,n-1) A[i]=2*s[i]*s[i];
rep(i,0,m-1) B[m-i-1]=t[i]*t[i];
NTT(A,len,1);NTT(B,len,1);
rep(i,0,len-1) A[i]=(ll)A[i]*B[i]%p;
NTT(A,len,-1);
int res=0;
rep(i,m-1,n-1) if(ans[i]==A[i]) res++;
printf("%d\n",res);
rep(i,m-1,n-1) if(ans[i]==A[i]) printf("%d\n",i-m+1);
return 0;
}

  

BZOJ4503: 两个串的更多相关文章

  1. bzoj4503: 两个串 bitset

    目录 题目链接 题解 代码 题目链接 bzoj4503: 两个串 题解 暴一发bitset f[i][j] 表示 S[1..i] 是否有个后缀能匹配 T[1..j] 那么假设 S[i+1] 能匹配 T ...

  2. BZOJ4259: 残缺的字符串 & BZOJ4503: 两个串

    [传送门:BZOJ4259&BZOJ4503] 简要题意: 给出两个字符串,第一个串长度为m,第二个串长度为n,字符串中如果有*字符,则代表当前位置可以匹配任何字符 求出第一个字符串在第二个字 ...

  3. BZOJ4503 两个串 多项式 FFT

    题目传送门 - BZOJ4503 题意概括 给定两个字符串S和T,回答T在S中出现了几次,在哪些位置出现.注意T中可能有?字符,可以匹配任何字符. 题解 首先,假装你已经知道了这是一道$FFT$题. ...

  4. 2019.02.06 bzoj4503: 两个串(fft)

    传送门 题意简述:给两个字符串s,ts,ts,t,ttt中可能有通配符,问ttt在sss出现的次数和所有位置. 思路:一道很熟悉的题,跟bzoj4259bzoj4259bzoj4259差不多的. 然后 ...

  5. BZOJ4503 两个串 【fft】

    题目链接 BZOJ4503 题解 水水题. 和残缺的字符串那题几乎是一样的 同样转化为多项式 同样TLE 同样要手写一下复数才A #include<algorithm> #include& ...

  6. BZOJ4503: 两个串(bitset字符串匹配)

    题意 题目链接 Sol Orz xudyh F个毛T啊..直接bitset一波就赢了啊...(虽然复杂度很假) 就是记录匹配串中每个元素出现的位置,将第\(i\)个位置的bitset右移\(i\)位后 ...

  7. 【BZOJ4503】两个串(FFT)

    [BZOJ4503]两个串(FFT) 题面 给定串\(S\),以及带通配符的串\(T\),询问\(T\)在\(S\)中出现了几次.并且输出对应的位置. \(|S|,|T|<=10^5\),字符集 ...

  8. 【BZOJ4503】两个串 FFT

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

  9. 【bzoj4259/bzoj4503】残缺的字符串/两个串 FFT

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

随机推荐

  1. java中常用的工具类(三)

    继续分享java中常用的一些工具类.前两篇的文章中有人评论使用Apache 的lang包和IO包,或者Google的Guava库.后续的我会加上的!谢谢支持IT江湖 一.连接数据库的综合类       ...

  2. 【数据结构】建立和平衡AVL二叉树

    一步一步写平衡二叉树(AVL树) 原文地址:http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html 我添加了一些内容,以充实整个算 ...

  3. android 入门-本地化语言

    打包安装到手机上,改变手机系统语言,你在看看是不是改变了.哇.真的可以.

  4. WPF中查看PDF文件

    需要打开PDF文件时,我们第一印象就是使用Adobe Reader.在开发中,经常会遇到需要展示PDF文件的需求.我们会借助于Adobe Reader的Active控件来实现.不过这需要客户的机器上安 ...

  5. hdu 5291 dp+优化 ****

    多校实在高能 题解链接 题意:有n中糖果,每种糖果有ai个.分给A,B两个人.两人的糖果要一样多,可以都是0,1......m个.同一种糖果没有区别. 问有几种分法. 定义dp[i]表示两人之间相差i ...

  6. OpenMesh 删除网格顶点

    OpenMesh 提供了 delete_vertex() 函数来实现从网格中删除顶点,在删除掉顶点的同时,所有与该顶点相连的边也同时被删除. OpenMesh 官方文档 中给的顶点删除函数声明如下: ...

  7. 数据库字典 sql

    SELECT 表名=case when a.colorder=1 then d.name else '' end, 表说明=case when a.colorder=1 then isnull(f.v ...

  8. 用计算器计算“异或CRC”

    再计算器上输入以下数字,每输入一个数字,按一下“Xor”

  9. Arduino101学习笔记(四)—— 数字IO

    1.设置管脚模式 //***************************************************************************************** ...

  10. Spring中属性文件properties的读取与使用

    实际项目中,通常将一些可配置的定制信息放到属性文件中(如数据库连接信息,邮件发送配置信息等),便于统一配置管理.例中将需配置的属性信息放在属性文件/WEB-INF/configInfo.propert ...