题目大意:给定一个文本串和一个模板串,串中含有通配符,求文本串中有多少个位置可以与文本串完全匹配。

题解:利用卷积求解字符串匹配问题。

通配符字符串匹配的数值表示为 $$\sum\limits_{i = 0}^{m - 1}(a[i] - b[i + k])^2 a[i]b[i + k]=0$$。直接展开之后计算三个卷积即可。

需要注意的是:并不是所有 a[i] b[i + k] 均为循环卷积,是否需要倍增取决于是否成环。

代码如下

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cp;
const double eps = 1e-8;
const double pi = acos(-1); int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> m >> n;
string s, t;
cin >> t >> s;
int tot = 1, bit = 0;
while (tot <= n + m) {
tot <<= 1;
++bit;
}
vector<int> rev(tot);
for (int i = 0; i < tot; i++) {
rev[i] = rev[i >> 1] >> 1 | (i & 1) << bit - 1;
}
vector<cp> a1(tot), a2(tot), a3(tot), b1(tot), b2(tot), b3(tot);
auto work = [](char ch) {
if (ch == '*') {
return 0;
} else {
return ch - 'a' + 1;
}
};
for (int i = 0; i < m; i++) {
int x = work(t[i]);
a1[m - 1 - i] = x;
a2[m - 1 - i] = x * x;
a3[m - 1 - i] = x * x * x;
}
for (int i = 0; i < n; i++) {
int x = work(s[i]);
b1[i] = x;
b2[i] = x * x;
b3[i] = x * x * x;
}
auto fft = [=](vector<cp> &v, int opt) {
for (int i = 0; i < tot; i++) {
if (i < rev[i]) {
swap(v[i], v[rev[i]]);
}
}
for (int mid = 1; mid < tot; mid <<= 1) {
cp wn(cos(pi / mid), opt * sin(pi / mid));
for (int j = 0; j < tot; j += mid << 1) {
cp w(1, 0);
for (int k = 0; k < mid; k++) {
cp x = v[j + k], y = w * v[j + mid + k];
v[j + k] = x + y, v[j + mid + k] = x - y;
w *= wn;
}
}
}
if (opt == -1) {
for (int i = 0; i < tot; i++) {
v[i].real(round(v[i].real() / tot));
}
}
};
auto calc = [=](vector<cp> &a, vector<cp> &b) {
fft(a, 1), fft(b, 1);
for (int i = 0; i < tot; i++) {
a[i] *= b[i];
}
fft(a, -1);
};
calc(a3, b1), calc(a2, b2), calc(a1, b3);
int ans = 0;
vector<int> pos;
for (int k = 0; k < n - m + 1; k++) {
double ret = a3[m + k - 1].real() - 2 * a2[m + k - 1].real() + a1[m + k - 1].real();
if (fabs(ret) < eps) {
++ans;
pos.push_back(k + 1);
}
}
cout << ans << endl;
for (auto p : pos) {
cout << p << " ";
}
return 0;
}

最新文章

  1. EF UoC
  2. macOS sierra 10.12 Cocoapods 私有库
  3. 软件测试第二次作业——Fault,Failure,Error辨析与设计测试用例
  4. javascript_22_for_js控制div每五个换一行
  5. 如何配置JAVA的环境变量、Tomcat环境变量
  6. treecnt
  7. node-webkit制作桌面应用
  8. ubantu10.04安装ns-2.34
  9. (cvpr 2018)Technology details of SMRD
  10. codeforces158C
  11. [Android] Android 去掉界面标题栏的方法
  12. centos安装fish shell
  13. 文件系统的block 数据库中的block 以及内存中的page基础知识汇总(自己理解 可能有误)
  14. 修改git用户密码
  15. TZOJ 数据结构期末历年题目
  16. linux命令(38):split 分割文件
  17. HBase的简单java操作
  18. Using Apache Spark and MySQL for Data Analysis
  19. C++11之std::future和std::promise
  20. redis配置master-slave模式

热门文章

  1. HR,OA,CRM,DRP,ERP什么意思?电商行业的特点?电商行业模式?专业术语?
  2. 【Aizu - 0558】Cheese(bfs)
  3. splite与join
  4. Oracle中分析函数
  5. Mysql优化深度解析
  6. 建立分表sql执行语句批量生成工具(自创)
  7. 如何实现一个简化版的 jQuery
  8. 比较接口:Comparable和Comparator
  9. leecode刷题(28)-- 二叉树的前序遍历
  10. 打不开Call Hierarchy和History的解决方法