【刷题】BZOJ 4503 两个串
Description
兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,
分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。
Input
两行两个字符串,分别代表S和T
Output
第一行一个正整数k,表示T在S中出现了几次
接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。
Sample Input
bbabaababaaaaabaaaaaaaabaaabbbabaaabbabaabbbbabbbbbbabbaabbbababababbbbbbaaabaaabbbbbaabbbaabbbbabab
a?aba?abba
Sample Output
0
HINT
S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”
Solution
将字符串转化
对于每个位置,如果 \(s_i\) 为正常字母,那么赋值为 \(s_i-96\) ,如果是问号,那么赋值为 \(0\)
S赋值出的数组是 \(x\) ,T赋值出的数组是 \(y\)
令S中一个位置的权值为 \(f(i)=\sum_{j=0}^{i}(x_{i-j}-y_{len_T-j})^2y_{i-j}\)
那么如果在S中以 \(i\) 位置结尾的子串能够和T匹配,\(f(i)=0\)
这还是不好算,但是这形式就是在提示我们要用套路了
把 \(y\) 数组反过来, \(f(i)=\sum_{j=0}^{i}(x_{i-j}-y_{j})^2y_{j}\)
拆开, \(f(i)=\sum_{j=0}^ix_{i-j}^2y_j-2x_{i-j}y_j^2+y_j^3\)
两个卷积加上一个三次方权值和
FFT求解就好了
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const db Pi=acos(-1.0);
const int MAXN=1<<19;
int n1,n2,n,m,rev[MAXN],sum,f[MAXN],cnt,nt,ans[MAXN];
char s1[MAXN],s2[MAXN];
struct Complex{
db real,imag;
inline Complex operator + (const Complex &A) const {
return (Complex){real+A.real,imag+A.imag};
};
inline Complex operator - (const Complex &A) const {
return (Complex){real-A.real,imag-A.imag};
};
inline Complex operator * (const Complex &A) const {
return (Complex){real*A.real-imag*A.imag,imag*A.real+real*A.imag};
};
};
Complex x[MAXN],y[MAXN],xf[MAXN],yf[MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void FFT(Complex *A,int tp)
{
for(register int i=0;i<n;++i)
if(i<rev[i])std::swap(A[i],A[rev[i]]);
for(register int l=2;l<=n;l<<=1)
{
Complex wn=(Complex){cos(2*Pi/l),sin(tp*2*Pi/l)};
for(register int i=0;i<n;i+=l)
{
Complex w=(Complex){1,0};
for(register int j=0;j<(l>>1);++j)
{
Complex A1=A[i+j],A2=w*A[i+j+(l>>1)];
A[i+j]=A1+A2;A[i+j+(l>>1)]=A1-A2;
w=w*wn;
}
}
}
}
int main()
{
scanf("%s",s1);scanf("%s",s2);
n1=strlen(s1);n2=strlen(s2);
m=n1+n2-1;
for(n=1;n<m;n<<=1)cnt++;
for(register int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
for(register int i=0;i<n1;++i)x[i].real=(s1[i]-'a'+1)*2,xf[i].real=x[i].real*x[i].real/4.0;
for(register int i=0;i<n2;++i)y[n2-i-1].real=(s2[i]=='?'?0:s2[i]-'a'+1);
for(register int i=0;i<n2;++i)sum+=y[i].real*y[i].real*y[i].real,yf[i].real=y[i].real*y[i].real;
FFT(x,1);FFT(y,1);FFT(xf,1);FFT(yf,1);
for(register int i=0;i<n;++i)x[i]=xf[i]*y[i]-x[i]*yf[i];
FFT(x,-1);
for(register int i=0;i<n1-n2+1;++i)
if((int)(x[n2+i-1].real/n+sum+0.5)==0)ans[++nt]=i;
write(nt,'\n');
for(register int i=1;i<=nt;++i)write(ans[i],'\n');
puts("");
return 0;
}
【刷题】BZOJ 4503 两个串的更多相关文章
- BZOJ 4503: 两个串 [FFT]
4503: 两个串 题意:兔子们在玩两个串的游戏.给定两个只含小写字母的字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有"?"字符,这个字符可以匹 ...
- bzoj 4503 两个串
Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字符. Input 两行两个字 ...
- bzoj 4503 两个串 快速傅里叶变换FFT
题目大意: 给定两个\((length \leq 10^5)\)的字符串,问第二个串在第一个串中出现了多少次.并且第二个串中含有单字符通配符. 题解: 首先我们从kmp的角度去考虑 这道题从字符串数据 ...
- BZOJ 4503 两个串(FFT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4503 [题目大意] 给出S串和T串,计算T在S中出现次数,T中有通配符'?'. [题解 ...
- bzoj 4503: 两个串【脑洞+FFT】
真实脑洞题 因为通配符所以导致t串实际有指数级别个,任何字符串相关算法都没有用 考虑一个新的匹配方法:设a串(模板串)长为n,从m串的i位置开始匹配:\( \sum_{i=0}^{n-1}(a[j]- ...
- BZOJ.4503.两个串(FFT/bitset)
题目链接 \(Description\) 给定两个字符串S和T,求T在S中出现了几次,以及分别在哪些位置出现.T中可能有'?'字符,这个字符可以匹配任何字符. \(|S|,|T|\leq 10^5\) ...
- bzoj 4503 两个串——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 翻转T,就变成卷积.要想想怎么判断. 因为卷积是乘积求和,又想到相等的话相减为0,所以 ...
- bzoj 4503 两个串 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 推式子即可: 不知怎的调了那么久,应该是很清晰的. 代码如下: #include< ...
- BZOJ 4503 两个串 ——FFT
[题目分析] 定义两个字符之间的距离为 (ai-bi)^2*ai*bi 如果能够匹配,从i到i+m的位置的和一定为0 但这和暴力没有什么区别. 发现把b字符串反过来就可以卷积用FFT了. 听说KMP+ ...
随机推荐
- elasticsearch集群整合elqsticsearch-sql插件
1.本来整合这个插件是比较简单易操作的,但是由于公司从AWS下载禁掉了,给安装带来一些麻烦, 采用离线安装,先FQ将elasticsearch-sql-5.1.2.0.zip下载下来: ./bin/e ...
- Android7.0 应用内升级
Android7.0应用内升级 最近线上项目在7.0机器上出现应用内升级失败,原来是由于Android7.0权限问题导致. 如果项目的 targetSdkVersion>=24 在处理应用内升级 ...
- unity3d 角色头顶信息3D&2D遮挡解决方案(二)
在阅读本文之前请先阅读上一篇文章:http://www.cnblogs.com/shenggege/p/4179012.html 本来一篇文章就可以说完了,但是上次只是实现了已知的一些功能 后来在实际 ...
- WeTest功能优化第1期:截图960px,云真机映射功能了解
第1期功能优化目录 [全线产品测试截图优化]安卓机型测试截图分辨率上升至960px [云真机新增Android 9]最新安卓系统,等你pick [云真机新增键盘映射功能]电脑键盘码字,云真机同步显示 ...
- 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)
题意与分析(CodeForces 551B) 这他妈哪里是日常训练,这是日常弟中弟. 题意是这样的,给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为 ...
- Qt-QPalette-调色板学习
已经很久没有更新博客了,一是因为换了公司,完全是断网开发了,没有时间来写博客,最主要的就是温水煮青蛙,自己在舒适的环境中越来越懒了,最近打算强制自己更新一波.不知道能坚持多久.由于目前没有具体的Qt项 ...
- pycharm 3.4 亲测可使用到2019年2月的注册码,要用者从速
注册码: D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1l ...
- selenium,unittest——两个class连续运行
将多个class放在一个文件内一起运行,这是一个多用例不同网站进行测试的方法 #encoding=utf-8from selenium import webdriverimport time,unit ...
- ortp打印日志
//向字符串中打印数据 static char* ms_strdup_vprintf(const char *fmt, va_list ap) { ; char *p,*np; #ifndef WIN ...
- lesson 18 Electric currents in modern art
lesson18 Electric currents in modern art electricity n. 电力:电流; electric adj. 电的:电动的; electronic adj. ...