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

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

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

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

代码如下

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef complex<double> cp;
  4. const double eps = 1e-8;
  5. const double pi = acos(-1);
  6. int main() {
  7. ios::sync_with_stdio(false);
  8. cin.tie(0);
  9. int n, m;
  10. cin >> m >> n;
  11. string s, t;
  12. cin >> t >> s;
  13. int tot = 1, bit = 0;
  14. while (tot <= n + m) {
  15. tot <<= 1;
  16. ++bit;
  17. }
  18. vector<int> rev(tot);
  19. for (int i = 0; i < tot; i++) {
  20. rev[i] = rev[i >> 1] >> 1 | (i & 1) << bit - 1;
  21. }
  22. vector<cp> a1(tot), a2(tot), a3(tot), b1(tot), b2(tot), b3(tot);
  23. auto work = [](char ch) {
  24. if (ch == '*') {
  25. return 0;
  26. } else {
  27. return ch - 'a' + 1;
  28. }
  29. };
  30. for (int i = 0; i < m; i++) {
  31. int x = work(t[i]);
  32. a1[m - 1 - i] = x;
  33. a2[m - 1 - i] = x * x;
  34. a3[m - 1 - i] = x * x * x;
  35. }
  36. for (int i = 0; i < n; i++) {
  37. int x = work(s[i]);
  38. b1[i] = x;
  39. b2[i] = x * x;
  40. b3[i] = x * x * x;
  41. }
  42. auto fft = [=](vector<cp> &v, int opt) {
  43. for (int i = 0; i < tot; i++) {
  44. if (i < rev[i]) {
  45. swap(v[i], v[rev[i]]);
  46. }
  47. }
  48. for (int mid = 1; mid < tot; mid <<= 1) {
  49. cp wn(cos(pi / mid), opt * sin(pi / mid));
  50. for (int j = 0; j < tot; j += mid << 1) {
  51. cp w(1, 0);
  52. for (int k = 0; k < mid; k++) {
  53. cp x = v[j + k], y = w * v[j + mid + k];
  54. v[j + k] = x + y, v[j + mid + k] = x - y;
  55. w *= wn;
  56. }
  57. }
  58. }
  59. if (opt == -1) {
  60. for (int i = 0; i < tot; i++) {
  61. v[i].real(round(v[i].real() / tot));
  62. }
  63. }
  64. };
  65. auto calc = [=](vector<cp> &a, vector<cp> &b) {
  66. fft(a, 1), fft(b, 1);
  67. for (int i = 0; i < tot; i++) {
  68. a[i] *= b[i];
  69. }
  70. fft(a, -1);
  71. };
  72. calc(a3, b1), calc(a2, b2), calc(a1, b3);
  73. int ans = 0;
  74. vector<int> pos;
  75. for (int k = 0; k < n - m + 1; k++) {
  76. double ret = a3[m + k - 1].real() - 2 * a2[m + k - 1].real() + a1[m + k - 1].real();
  77. if (fabs(ret) < eps) {
  78. ++ans;
  79. pos.push_back(k + 1);
  80. }
  81. }
  82. cout << ans << endl;
  83. for (auto p : pos) {
  84. cout << p << " ";
  85. }
  86. return 0;
  87. }

【洛谷P4173】残缺的字符串的更多相关文章

  1. 洛谷 P4173 残缺的字符串 (FFT)

    题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...

  2. 洛谷P4173 残缺的字符串(FFT)

    传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...

  3. 洛谷P4173 残缺的字符串

    题目大意: 两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置 字符串长度\(\le 300000\) 考虑魔改一发\(kmp\),发现魔改不出来 于是考虑上网搜题解 然后考虑\ ...

  4. 洛谷 P4173 残缺的字符串

    (不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...

  5. Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用

    P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...

  6. P4173 残缺的字符串(FFT字符串匹配)

    P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...

  7. BZOJ1856或洛谷1641 [SCOI2010]生成字符串

    BZOJ原题链接 洛谷原题链接 可以将\(1\)和\(0\)的个数和看成是\(x\)轴坐标,个数差看成\(y\)轴坐标. 向右上角走,即\(x\)轴坐标\(+1\),\(y\)轴坐标\(+1\),表示 ...

  8. 卡特兰数 洛谷P1641 [SCOI2010]生成字符串

    卡特兰数 参考博客 介绍 卡特兰数为组合数学中的一种特殊数列,用于解决一类特殊问题 设\(f(n)\)为卡特兰数的第n项 其通项公式为 \[f(n)=\frac{2n\choose n}{n+1} \ ...

  9. 洛谷 P1641 [SCOI2010]生成字符串

    洛谷 这题一看就是卡塔兰数. 因为\(cnt[1] \leq cnt[0]\),很显然的卡塔兰嘛! 平时我们推导卡塔兰是用一个边长为n的正方形推的, 相当于从(0,0)点走到(n,n)点,向上走的步数 ...

  10. 洛谷P1852 奇怪的字符串

    题目描述 输入两个01串,输出它们的最长公共子序列的长度 输入输出格式 输入格式: 一行,两个01串 输出格式: 最长公共子序列的长度 输入输出样例 输入样例#1: 复制 01010101010 00 ...

随机推荐

  1. web端测试之封装公共部分

    from time import * from selenium import webdriver def login(self,username,passwd): self.dr=webdriver ...

  2. LeetCode.1103-向人们分发糖果(Distribute Candies to People)

    这是小川的第393次更新,第425篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第256题(顺位题号是1103).我们通过以下方式向一排n = num_people个人分 ...

  3. Misc题目

    @freebuff教程https://www.freebuf.com/column/196815.html @巅峰极客wp https://www.anquanke.com/post/id/18914 ...

  4. mint ui解决Navbar和Infinite scroll共存时的bug

    Navbar和Infinite scroll共同使用时会出现无限加载的问题,滑动也会出现乱加载. 只需要判断一下就可以了,代码: html: <mt-navbar v-model="s ...

  5. 8.X版本的node打包时,gulp命令报错 require.extensions.hasownproperty

    版本不兼容的问题,低版本的gulp只能在低版本的node上执行. 修改一下node-modules/require-dir/index.js的97行代码即可,如下:

  6. Tableau常用函数、功能

    Tableau常用函数 创建计算字段: Tableau常用功能

  7. SpreadJS与Vue集成,苏宁集团『极客办公』系统开发案例

    “造极”如今已成为苏宁集团的年度核心关键词.“造极”在具体工作上的体现,代表着苏宁不断追求极致的工匠精神,即对待每一个环节,都要严格要求.精益求精.“极客办公”系统,正是在这种环境下应运而生.本期公开 ...

  8. 完全删除MySQL及相关软件

    一.删除mysql服务 个人认为首先删除mysql服务最重要,这个多数人会忘记如何删除 首先是查看自己的mysql服务名,需要用这个服务名进行删除 进入命令行 二.卸载mysql,workbench等 ...

  9. AppCan全局搜索

    Ctrl + H,在项目中全局搜索英文和中文

  10. six库 解决python2的项目如何能够完全迁移到python3

    six库 解决python2的项目如何能够完全迁移到python3 SIX是用于python2与python3兼容的库. 它存在的目的是为了拥有无需修改即可在Python 2和Python 3上同时工 ...