[Luogu P4173]残缺的字符串 ( 数论 FFT)
题面
传送门:洛咕
Solution
这题我写得脑壳疼,我好菜啊
好吧,我们来说正题。
这题.....emmmmmmm
显然KMP类的字符串神仙算法在这里没法用了。
那咋搞啊(或者说这题和数学有半毛钱关系啊)
我们考虑把两个字符相同强行变为一个数学关系,怎么搞呢?
考虑这题是带通配符的,我们可以这样设:
\(C(x,y)=(A[x]-B[y])^2*A[x]*B[y]\)
因此,我们可以看出两个字符一样当且仅当\(C(x,y)=0\)
因此,我们再设一个函数\(P(x)\)表示\(B\)串以第\(x\)项为结尾的长度为\(m\)的子串是否与\(A\)串匹配,显然有:
\(P(x)=\sum_{i=0}^{m-1}C(i,x-m+i+1)\)
\(P(x)=\sum_{i=0}^{m-1}(A[i]-B[x-m+i+1])^2*A[i]*B[x-m+i+1]\)
后面那个式子写的太蛋疼了,我们把\(x-m+i+1\)设为\(j\)吧。
\(P(x)=\sum_{i=0}^{m-1}(A[i]-B[j])^2*A[i]*B[j]\)
大力展开得:
\(P(x)=\sum_{i=0}^{m-1}A[i]^3B[j]-2A[i]^2B[j]^2+A[i]B[j]^3\)
然后.....我们试着把\(\sum\)展开?
\(P(x)=\sum_{i=0}^{m-1}A[i]^3B[j]-\sum_{i=0}^{m-1}2A[i]^2B[j]^2+\sum_{i=0}^{m-1}A[i]B[j]^3\)
还是没法算啊......
诶,等下,如果我们把\(A\)串反转为\(A'\),肯定有\(A[i]=A'[m-i-1]\)
然后这个\((m-i-1)+(j)\)......不就是等于\(x\)嘛。
所以说我们马上就有:
\(P(x)=\sum_{i+j=x}A[i]^3B[j]-\sum_{i+j=x}2A[i]^2B[j]^2+\sum_{i+j=x}A[i]B[j]^3\)
哦豁,卷积,搞定~
时间复杂度\(O(nlogn)\)
搞定个鬼,这题要做7次FFT,常数爆大,我卡不进去
还请各位dalao赐教。
Code
#include<iostream>
#include<cstdio>
#include<complex>
#include<cmath>
#include<algorithm>
using namespace std;
const int M=300000+100;
const int N=M*4;
const double PI=acos(-1);
const double eps=1e-1;
typedef complex <double> cp;
cp omega(int K,int n)
{
return cp(cos(2*PI*K/n),sin(2*PI*K/n));
}
inline void FFT(cp a[],int n,bool type)
{
static int tmp[N],num=n-1,len;
while(num!=0) num/=2,len++;
for(int i=0,j;i<=n;i++)
{
for(j=0,num=i;j<len;j++)
tmp[j]=num%2,num/=2;
reverse(tmp,tmp+len);
for(j=0,num=0;j<len;j++)
num+=tmp[j]*(1<<j);
if(i<num) swap(a[i],a[num]);
}
for(int l=2;l<=n;l*=2)
{
int m=l/2;
cp x0=omega(1,l);
if(type==true) x0=conj(x0);
for(int i=0;i<n;i+=l)
{
cp x(1,0);
for(int j=0;j<m;j++,x*=x0)
{
cp temp=x*a[i+j+m];
a[i+j+m]=a[i+j]-temp;
a[i+j]=a[i+j]+temp;
}
}
}
}
char A[N],B[N];
int m,n,t=1;
cp S1[N],S2[N],S3[N],B1[N],B2[N],B3[N];
bool OK[N];
int main()
{
scanf("%d%d%s%s",&m,&n,A,B);
while(t<=(n+m)) t*=2;
reverse(A,A+m);
for(int i=0;i<t;i++)
A[i]=(A[i]=='*' or A[i]<'a' or A[i]>'z'?0:A[i]-'a'+1),
B[i]=(B[i]=='*' or B[i]<'a' or B[i]>'z'?0:B[i]-'a'+1);
for(int i=0;i<t;i++)
S1[i]=A[i],S2[i]=A[i]*A[i],S3[i]=A[i]*A[i]*A[i];
for(int i=0;i<t;i++)
B1[i]=B[i],B2[i]=B[i]*B[i],B3[i]=B[i]*B[i]*B[i];
FFT(S1,t,false);
FFT(S2,t,false);
FFT(S3,t,false);
FFT(B1,t,false);
FFT(B2,t,false);
FFT(B3,t,false);
for(int i=0;i<t;i++)
S3[i]*=B1[i];
for(int i=0;i<t;i++)
S1[i]*=B3[i];
for(int i=0;i<t;i++)
S2[i]*=B2[i];
for(int i=0;i<t;i++)
S3[i]+=S1[i]-2.0*S2[i];
FFT(S3,t,true);
int cnt=0;
for(int i=m-1;i<n;i++)
if(fabs(S3[i].real()/t)<eps)
OK[i]=true,cnt++;
printf("%d\n",cnt);
for(int i=m-1;i<n;i++)
if(OK[i]==true)
printf("%d ",i-m+1+1);
return 0;
}
[Luogu P4173]残缺的字符串 ( 数论 FFT)的更多相关文章
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- 洛谷P4173 残缺的字符串(FFT)
传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...
- luogu P4173 残缺的字符串
传送门 两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是\(*\)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m 然而上面那个做法在字符集大 ...
- P4173 残缺的字符串(FFT)
[Luogu4173] 题解 \(1.\)定义匹配函数 \(2.\)定义完全匹配函数 \(3.\)快速计算每一位的完全匹配函数值 #include<cstdio> #include< ...
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
- 【BZOJ4259】残缺的字符串(FFT)
[BZOJ4259]残缺的字符串(FFT) 题面 给定两个字符串\(|S|,|T|\),两个字符串中都带有通配符. 回答\(T\)在\(S\)中出现的次数. \(|T|,|S|<=300000\ ...
- P4173 残缺的字符串 fft
题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...
- BZOJ4259 残缺的字符串(FFT)
两个串匹配时相匹配的位置位置差是相同的,那么翻转一个串就变成位置和相同,卷积的形式. 考虑如何使用卷积体现两个位置能否匹配.一个暴力的思路是每次只考虑一种字符,将其在一个串中设为1,并在另一个串中将不 ...
随机推荐
- ACMer不得不会的线段树,究竟是种怎样的数据结构?
大家好,欢迎阅读周三算法数据结构专题,今天我们来聊聊一个新的数据结构,叫做线段树. 线段树这个数据结构很多人可能会有点蒙,觉得没有听说过,但是它非常非常有名,尤其是在竞赛圈,可以说是竞赛圈的必备技能. ...
- Web Storage API的介绍和使用
目录 简介 浏览器的本地存储技术 Web Storage相关接口 浏览器兼容性 隐身模式 使用Web Storage API 总结 简介 Web Storage为浏览器提供了方便的key value存 ...
- kubernetes1.15极速部署prometheus和grafana
关于prometheus和grafana prometheus负责监控数据采集,grafana负责展示,下图来自官网: 环境信息 硬件:三台CentOS 7.7服务器 kubernetes:1.15 ...
- jvm优化案例
案例1 survivor区太小,每次Minor GC存活的对象进入老年代,导致老年代可用空间不足,经常发生FULL GC,导致系统变慢 案例问题描述 有一个数据计算系统,从mysql和其他数据源提取数 ...
- c++ 中预编译头文件名 pch.h
转载:https://www.it-swarm.asia/zh/c++/%e6%88%91%e5%8f%af%e4%bb%a5%e4%bd%bf%e7%94%a8includepchh%e2%80%9 ...
- P2652 同花顺
P2652 同花顺 Link 题目背景 所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续. 题目描述 现在我手里有 \(n\) 张扑克牌,但它们可能并不能凑成同花顺.我现在想知道,最少更换其中 ...
- shell脚本中,关于if,以及条件判断
#!/bin/sh SYSTEM=`uname -s` #获取操作系统类型 if [ $SYSTEM = "Linux" ] ; then #如果是linux的话打印linux字符 ...
- python程序整理(2)
# 写一个函数完成三次登陆功能: # 用户的用户名密码从一个文件register中取出. # register文件包含多个用户名,密码,用户名密码通过|隔开,每个人的用户名密码占用文件中一行. # 完 ...
- jquery的实时触发事件(textarea实时获取中文个数)
jquery的实时触发事件(textarea实时获取中文个数) (2014-09-16 11:49:50) 转载▼ 标签: 实时触发事件 中文个数 onpropertychange oninput o ...
- CentOS 7基础命令介绍
01 CentOS基础命令介绍 重所周知,Linux是一个主要通过命令行来进行管理的操作系统,即通过键盘输入指令来管理系统的相关操作,包括但不限于编辑文件.启动/停止服务等.这和初学者曾经使用的Win ...