FFT字符串匹配(解决通配符问题)

FFT字符串匹配

定义字符串下标从000,开始,有文本串AAA长度为nnn,模式串BBB长度为mmm,我们可以考虑一个函数f(x,y)=A(x)−B(y)f(x, y) = A(x) - B(y)f(x,y)=A(x)B(y)

我们设F(x)(x≥m−1)=∑i=0m−1f(x−m+1+i,i)F(x)(x \ge m - 1) = \sum\limits_{i = 0} ^{m - 1} f(x - m + 1 + i, i)F(x)(xm1)=i=0m1f(xm+1+i,i),由定义显然可以得到如果F(x)=0F(x) = 0F(x)=0,则A[x−m+1,x]=BA[x - m + 1, x] = BA[xm+1,x]=B也就是两个字符匹配上了,

但是考虑"ab","ba""ab", "ba""ab","ba"两个字符串,他们也是匹配的,我们稍微修改一下f(x,y)f(x, y)f(x,y)函数令其为:(A(x)−B(y))2(A(x) - B(y)) ^ 2(A(x)B(y))2,这样这个函数就没有问题了。

我们考虑翻转一下BBB串,令其为SSS,则有B(i)=S(m−i−1)B(i) = S(m - i - 1)B(i)=S(mi1)
F(x)=∑i=0m−1(A(x−m+1+i)−S(m−i−1))2F(x)=∑i=0m−1S(m−i−1)2+∑i=0m−1A(x−m+1+i)2−2×∑i=0m−1A(x−m+1+i)S(m−i−1)F(x) = \sum\limits_{i = 0} ^{m - 1} \left(A(x - m + 1 + i) - S(m - i - 1)\right) ^ 2\\ F(x) = \sum_{i = 0} ^{m - 1} S(m - i - 1) ^ 2 + \sum_{i = 0} ^{m - 1} A(x - m + 1 + i) ^ 2 - 2 \times \sum_{i = 0} ^{m - 1} A(x - m + 1 + i) S(m - i - 1)\\ F(x)=i=0m1(A(xm+1+i)S(mi1))2F(x)=i=0m1S(mi1)2+i=0m1A(xm+1+i)22×i=0m1A(xm+1+i)S(mi1)
第一项是一个定值,第二可以O(n)O(n)O(n)预处理,然后前缀和O(1)O(1)O(1)得到,第三项不难发现是一个卷积的形式,所以可以通过FFTFFTFFT得到,整体复杂度O(nlog⁡n)O(n \log n)O(nlogn)

以上我们已经可以解决当模式串的字符串匹配了,尽管复杂度不如KMPKMPKMP优秀,但是我们考虑一个缺项字符串匹配:

a*b

aebr*ob

我们考虑重新设计f(x,y)f(x, y)f(x,y)函数,定义f(x,y)=(A(x)−B(y))2A(x)B(y)f(x, y) = (A(x) - B(y)) ^ 2 A(x) B(y)f(x,y)=(A(x)B(y))2A(x)B(y),同样的考虑翻转BBB串,有B(i)=S(m−1−i)B(i) = S(m - 1 - i)B(i)=S(m1i)
F(x)=∑i=0m−1(A(x−m+1+i)−S(m−1−i))2A(x−m+1+i)S(m−1−i)∑i=0m−1A(x−m+1+i)S(m−1−i)3+∑i=0m−1A(x−m+1+i)3S(m−1−i)−2×∑i=0m−1A(x−m+1+i)2S(m−1−i)2F(x) = \sum_{i = 0} ^{m - 1} (A(x - m + 1 + i) - S(m - 1 - i)) ^ 2 A(x - m + 1 + i) S(m - 1 - i)\\ \sum_{i = 0} ^{m - 1}A(x - m + 1 + i) S(m - 1 - i) ^ 3 + \sum_{i = 0} ^{m - 1} A(x - m + 1 + i) ^ 3 S(m - 1 - i) - 2 \times \sum_{i = 0} ^{m - 1} A(x - m + 1 + i) ^ 2 S(m - 1 - i) ^ 2\\ F(x)=i=0m1(A(xm+1+i)S(m1i))2A(xm+1+i)S(m1i)i=0m1A(xm+1+i)S(m1i)3+i=0m1A(xm+1+i)3S(m1i)2×i=0m1A(xm+1+i)2S(m1i)2
容易发现这里是三个多项式相加的形式,所以只要做三次FFTFFTFFT即可得到答案,放一个模板题。

#include <bits/stdc++.h>using namespace std;struct Complex {double r, i;Complex(double _r = 0, double _i = 0) : r(_r), i(_i) {}
};Complex operator + (const Complex &a, const Complex &b) {return Complex(a.r + b.r, a.i + b.i);
}Complex operator - (const Complex &a, const Complex &b) {return Complex(a.r - b.r, a.i - b.i);
}Complex operator * (const Complex &a, const Complex &b) {return Complex(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r);
}Complex operator / (const Complex &a, const Complex &b) {return Complex((a.r * b.r + a.i * b.i) / (b.r * b.r + b.i * b.i), (a.i * b.r - a.r * b.i) / (b.r * b.r + b.i * b.i));
}Complex operator * (const Complex &a, const double &b) {return Complex(a.r * b, a.i * b);
}const int N = 2e6 + 10;int r[N];void get_r(int lim) {for (int i = 0; i < lim; i++) {r[i] = (i & 1) * (lim >> 1) + (r[i >> 1] >> 1);}
}void FFT(Complex *f, int lim, int rev) {for (int i = 0; i < lim; i++) {if (i < r[i]) {swap(f[i], f[r[i]]);}}const double pi = acos(-1.0);for (int mid = 1; mid < lim; mid <<= 1) {Complex wn = Complex(cos(pi / mid), rev * sin(pi / mid));for (int len = mid << 1, cur = 0; cur < lim; cur += len) {Complex w = Complex(1, 0);for (int k = 0; k < mid; k++, w = w * wn) {Complex x = f[cur + k], y = w * f[cur + mid + k];f[cur + k] = x + y, f[cur + mid + k] = x - y;}}}if (rev == -1) {for (int i = 0; i < lim; i++) {f[i].r /= lim;}}
}// const int N = 1e6 + 10;Complex a[N], b[N], c[N];char str1[N], str2[N];int A[N], S[N], n, m, lim;int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);scanf("%d %d %s %s", &m, &n, str2, str1);for (int i = 0; i < n; i++) {A[i] = str1[i] == '*' ? 0 : str1[i] - 'a' + 1;}for (int i = 0; i < m; i++) {S[i] = str2[m - i - 1] == '*' ? 0 : str2[m - i - 1] - 'a' + 1;}lim = 1;while (lim < n + m) {lim <<= 1;}get_r(lim);for (int i = 0; i < lim; i++) {b[i] = Complex(A[i], 0);c[i] = Complex(S[i] * S[i] * S[i], 0);}FFT(b, lim, 1), FFT(c, lim, 1);for (int i = 0; i < lim; i++) {a[i] = a[i] + b[i] * c[i];}for (int i = 0; i < lim; i++) {b[i] = Complex(A[i] * A[i] * A[i], 0);c[i] = Complex(S[i], 0);}FFT(b, lim, 1), FFT(c, lim, 1);for (int i = 0; i < lim; i++) {a[i] = a[i] + b[i] * c[i];}for (int i = 0; i < lim; i++) {b[i] = Complex(A[i] * A[i], 0);c[i] = Complex(S[i] * S[i], 0);}FFT(b, lim, 1), FFT(c, lim, 1);for (int i = 0; i < lim; i++) {a[i] = a[i] - 2 * b[i] * c[i];}FFT(a, lim, -1);vector<int> ans;for (int i = m - 1; i < n; i++) {if ((long long)(a[i].r + 0.5) == 0) {ans.push_back(i - m + 2);}}printf("%d\n", ans.size());for (auto it : ans) {printf("%d ", it);}puts("");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记一次中小公司的研发问题

作者&#xff1a;zollty&#xff0c;资深程序员和架构师&#xff0c;私底下是个爱折腾的技术极客&#xff0c;架构师社区合伙人&#xff01;一、一些不好的现状&#xff0c;及对应的改进方法1、前后端代码绑定在一起&#xff0c;很难维护&#xff0c;前端UI做得太差&#xff0c…

命令行操作mysql

1、通过命令行连接mysql&#xff1a; 1、输入命令&#xff1a;mysql -h localhost&#xff08;服务IP地址&#xff09; -u root&#xff08;用户名&#xff09; -P 3306&#xff08;服务端口&#xff09;-p 2、输入密码 2、显示数据库、表&#xff1a; show databases; //…

2021CCPC华为云挑战赛:HDU 7091 重叠的子串(SAM + 线段树合并)

重叠的子串 给定一个长度为n(1≤∣s∣≤105)n(1 \le \mid s \mid \le 10 ^ 5)n(1≤∣s∣≤105)的只由小写字母构成的字符串sss&#xff0c;有m,(1≤m≤106)m, (1 \le m \le 10 ^ 6)m,(1≤m≤106)个询问&#xff1a; 每次询问给定l,rl, rl,r&#xff0c;问sss是否存在一个字串…

ASP.NET Core 3.0 使用gRPC

一.简介gRPC 是一个由Google开源的&#xff0c;跨语言的&#xff0c;高性能的远程过程调用&#xff08;RPC&#xff09;框架。gRPC使客户端和服务端应用程序可以透明地进行通信&#xff0c;并简化了连接系统的构建。它使用HTTP/2作为通信协议&#xff0c;使用 Protocol Buffers…

mysql 1030 error:Got error 28 from storage engine

最近生产应用连不上生产环境数据库&#xff0c;使用命令行连上去之后&#xff0c;执行命令出现1030 error。 故Google之&#xff0c;解决方案如下。 mysql 1030 error 是因为没有足够的空间&#xff0c;清理磁盘空间即可恢复正常使用。 然后追踪发现&#xff0c;磁盘空间为99G&…

Codeforces Round #739 (Div. 3)(AK实况)

Codeforces Round #739 (Div. 3) A. Dislike of Threes 找到第kkk个既不是333的倍数&#xff0c;个位数上也不是333的数&#xff0c;也已预处理然后O(1)O(1)O(1)输出&#xff0c;也可直接forforfor循环暴力。 #include <bits/stdc.h>using namespace std;int main() {/…

利用Helm简化Kubernetes应用部署(2)

目录定义Charts 使用Helm部署Demo Helm常用操作命令 定义Charts回到之前的“charts”目录&#xff0c;我们依次进行解读并进行简单的修改。Chart.yaml配置示例&#xff1a;apiVersion: v1 appVersion: "1.1" description: A demo Helm chart for Kubernetes name:…

linux查看磁盘空间命令

Linux 查看磁盘空间可以使用 df 和 du 命令。 df df 以磁盘分区为单位查看文件系统&#xff0c;可以获取硬盘被占用了多少空间&#xff0c;目前还剩下多少空间等信息。 例如&#xff0c;我们使用df -h命令来查看磁盘信息&#xff0c; -h 选项为根据大小适当显示&#xff1a; …

Visual Studio 2019 16.3 正式发布,支持 .NET Core 3.0

微软正式发布了 Visual Studio 2019 16.3 版本&#xff0c;主要更新内容如下&#xff1a;.NET Core 3.0Visual Studio 版本 16.3 包括对 .NET Core 3.0 的支持。注意&#xff1a;如果使用的是 .NET Core 3.0&#xff0c;则需要使用 Visual Studio 16.3 或更高版本。.NET Core 桌…

Linux清空文件内容的三种方法

Linux清空文件内容的三种方法 测试文件&#xff1a;test.txt 1、 $ > test.txt 2、 $echo “” > test.txt 3、 $cat /dev/null > test.txt

Problem M. Mediocre String Problem(Z 函数 + PAM)

Problem M. Mediocre String Problem 给定两个串s,ts, ts,t&#xff0c;要求有多少不同的三元组(i,j,k)(i, j, k)(i,j,k)&#xff0c;满足&#xff1a; 1≤i≤j≤∣s∣1 \le i \le j \le \mid s \mid1≤i≤j≤∣s∣。1≤k≤∣t∣1 \le k \le \mid t \mid1≤k≤∣t∣。j−i1≥k…

【干货】规模化敏捷DevOps四大实践之持续探索CE(中英对照版)

本文翻译来自SAFe DevOps社群帅哥网友贾磊&#xff1a;高级质量经理&敏捷教练 曾就职于外企、国企、大型上市企业等&#xff0c;担任过测试工程师、测试经理、项目经理、敏捷教练、质量总监、高级质量经理等岗位。是一名敏捷变革的爱好者和践行者。爱好网球、羽毛球。正文原…

Spring Cloud——Eureka——架构体系

1、概述 Eureka包括两个端&#xff1a; Eureka Server&#xff1a;注册中心服务端&#xff0c;用于维护和管理注册服务列表。Eureka Client&#xff1a;注册中心客户端&#xff0c;向注册中心注册服务的应用都可以叫做Eureka Client&#xff08;包括Eureka Server本身&#x…

C - Maximize GCD(简单数论)

C - Maximize GCD 给定长度为n,(2≤3105)n, (2 \le 3 \times 10 ^ 5)n,(2≤3105)的数组a,(1≤ai≤3105)a, (1 \le a_i \le 3 \times 10 ^ 5)a,(1≤ai​≤3105)&#xff0c;一个数字K,(1≤K≤1018)K, (1 \le K \le 10 ^{18})K,(1≤K≤1018)&#xff0c; 我们可以对数组aaa进行…

推荐.neter常用优秀开源项目系列之二

.net社区有很多优秀的开源项目&#xff0c;我们今天再推荐12个开源项目&#xff1b;1. Domain-Driven-Design-ExampleDDD 示例 挺不错的。github https://github.com/zkavtaskin/Domain-Driven-Design-Example2.SmartStoreNET开源的电商项目github https://github.com/smartsto…

Zookeeper: Zookeeper架构及FastLeaderElection机制

本文转发自技术世界&#xff0c;原文链接 http://www.jasongj.com/zookeeper/fastleaderelection/ 一、Zookeeper是什么 Zookeeper是一个分布式协调服务&#xff0c;可用于服务发现&#xff0c;分布式锁&#xff0c;分布式领导选举&#xff0c;配置管理等。 这一切的基础&am…

I. Rise of Shadows(类欧几里得)

I. Rise of Shadows 一天有HHH个小时&#xff0c;MMM分钟&#xff0c;问&#xff0c;有多少个整数分钟&#xff0c;满足时针与分针的角度≤α\le \alpha≤α&#xff0c;α2πAHM\alpha \frac{2 \pi A}{HM}αHM2πA​。 ∑i0H−1∑j0M−1[∣2π(iMj)HM−2πjM∣≤2πAHM]∑i0…

与时俱进 | 博客现已运行在 .NET Core 3.0 及 Azure 上

点击上方蓝字关注“汪宇杰博客”导语9月23日&#xff0c;微软正式发布了 .NET Core 3.0&#xff0c;这个版本具有大量新功能和改进。我也在第一时间将自己的博客网站更新到了 .NET Core 3.0&#xff0c;并且仍然跑在微软智慧云 Azure 国际版的应用服务上。本文总结了我在博客迁…

Zookeeper:基于Zookeeper的分布式锁与领导选举

本文转发自技术世界&#xff0c;原文链接 http://www.jasongj.com/zookeeper/distributedlock/ 1、Zookeeper特点 1.1 Zookeeper节点类型 如上文《Zookeeper架构及FastLeaderElection机制》所述&#xff0c;Zookeeper 提供了一个类似于 Linux 文件系统的树形结构。该树形结构…

Asp.Net Core Mvc Razor之RazorPage

在AspNetCore.Mvc.Razor命名空间中的RazorPage继承RazorPageBase&#xff0c;并定义的属性为&#xff1a;HttpContext Context 表示当前请求执行的HttpContextRazorPageBase定义为抽象类&#xff0c;并继承了接口&#xff1a;IRazorPageIRazorPage接口定义属性如下&#xff1a;…