【BZOJ 4259】残缺的字符串

传送门


Problem

给出长度为 m m m 的串 A A A 和长度为 n n n 的串 B B B A A A 为模板串), ∗ * 号表示这个位置可以是任意字母。对于字符串 B B B,求出每个可以与 A A A 匹配的开头位置(下标从 1 1 1 开始)。

数据范围: 1 ≤ m ≤ n ≤ 300000 1\le m\le n\le300000 1mn300000


Solution

这个 ∗ * 限制了我们的字符串算法。。。

假设 B B B 从第 j j j 位开始与 A A A 匹配,定义 f j = ∑ i = 0 m − 1 ( A i − B i + j ) 2 A i B i + j f_j=\sum_{i=0}^{m-1}(A_i-B_{i+j})^2A_iB_{i+j} fj=i=0m1(AiBi+j)2AiBi+j,然后令 ∗ * 的权值为 0 0 0

发现当 A , B A,B A,B 能匹配的情况只有当 f j = 0 f_j=0 fj=0 时。

仔细想一想, ( A i − B i ) 2 = 0 (A_i-B_i)^2=0 (AiBi)2=0 就是 A i = B i A_i=B_i Ai=Bi 的情况, A i = 0 A_i=0 Ai=0 就是 A A A 中有 ∗ * B i = 0 B_i=0 Bi=0 同理。

那么一样的套路,我们把 A A A 翻转一下,把下标扩展到 n n n,于是就有:

f j = ∑ i = 0 n − 1 ( A n − i + 1 − B i + j ) 2 A n − i + 1 B i + j f_j=\sum_{i=0}^{n-1}(A_{n-i+1}-B_{i+j})^2A_{n-i+1}B_{i+j} fj=i=0n1(Ani+1Bi+j)2Ani+1Bi+j

发现下标之和为 n − j + 1 n-j+1 nj+1,在 j j j 一定时为定值(即为卷积的形式)。

把它展开:

f j = ∑ i = 0 n − 1 A n − i + 1 3 B i + j − 2 ∑ i = 0 n − 1 A n − i + 1 2 B i + j 2 + ∑ i = 0 n − 1 A n − i + 1 B i + j 3 f_j=\sum_{i=0}^{n-1}A_{n-i+1}^3B_{i+j}-2\sum_{i=0}^{n-1}A^2_{n-i+1}B^2_{i+j}+\sum_{i=0}^{n-1}A_{n-i+1}B^3_{i+j} fj=i=0n1Ani+13Bi+j2i=0n1Ani+12Bi+j2+i=0n1Ani+1Bi+j3

于是用 f f t fft fft,判断一下 f j f_j fj 是否为 n n n 即可。


Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300005
#define ll long long
using namespace std;
const double pi=acos(-1);
int n,m,lim=1,tot;
int x[N],y[N],pos[N<<2],rec[N];
char A[N],B[N];
ll ans[N];
struct complex{
	double x,y;
	complex(){}
	complex(double x,double y):x(x),y(y){}
	friend complex operator+(const complex &a,const complex &b)  {return complex(a.x+b.x,a.y+b.y);}
	friend complex operator-(const complex &a,const complex &b)  {return complex(a.x-b.x,a.y-b.y);}
	friend complex operator*(const complex &a,const complex &b)  {return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
}a[N<<2],b[N<<2];
void DFT(complex f[],int type){
	for(int i=0;i<lim;++i)
		if(pos[i]>i)  swap(f[i],f[pos[i]]);
	for(int mid=1;mid<lim;mid<<=1){
		complex now=complex(cos(pi/mid),type*sin(pi/mid));
		for(int i=0;i<lim;i+=(mid<<1)){
			complex w=complex(1,0);
			for(int j=0;j<mid;++j,w=w*now){
				complex p0=f[i+j],p1=w*f[i+j+mid];
				f[i+j]=p0+p1,f[i+j+mid]=p0-p1;
			}
		}
	}
	if(type==-1)  for(int i=0;i<lim;++i)  f[i].x/=lim;
}
void FFT(int k){
	DFT(a,1),DFT(b,1);
	for(int i=0;i<lim;++i)  a[i]=a[i]*b[i];
	DFT(a,-1);
	for(int i=0;i<n;++i)  ans[i]+=k*(ll)(a[i].x+0.5);
	for(int i=0;i<lim;++i)  a[i].x=a[i].y=b[i].x=b[i].y=0;
}
int main(){
	scanf("%d%d%s%s",&m,&n,A,B);
	while(lim<=(n<<1))  lim<<=1;
	for(int i=0;i<lim;++i)  pos[i]=(pos[i>>1]>>1)|((i&1)*(lim>>1));
	for(int i=0;i<m;++i)  if(A[i]!='*')  x[i]=A[i]-'a'+1;
	for(int i=0;i<n;++i)  if(B[i]!='*')  y[i]=B[i]-'a'+1;
	reverse(x,x+m);
	for(int i=0;i<n;++i)a[i].x=x[i]*x[i]*x[i],b[i].x=y[i];FFT(1);
	for(int i=0;i<n;++i)a[i].x=x[i]*x[i],b[i].x=y[i]*y[i];FFT(-2);
	for(int i=0;i<n;++i)a[i].x=x[i],b[i].x=y[i]*y[i]*y[i];FFT(1);
	for(int i=m-1;i<n;++i)  if(!ans[i])  rec[++tot]=i-m+2;
	printf("%d\n",tot);
	for(int i=1;i<=tot;++i)  printf("%d ",rec[i]);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值