题目

很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?

输入格式

第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。
第二行为一个长度为m的字符串A。
第三行为一个长度为n的字符串B。
两个串均仅由小写字母和号组成,其中号表示相应位置已经残缺。

输出格式

第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。
若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。

输入样例

3 7

a*b

aebr*ob

输出样例

2

1 5

题解

似乎字符串相关数据结构很难解决这个问题,我们考虑量化匹配关系

我们尝试构造两个多项式,
如果我们能让匹配的位置通过某种运算为0,似乎就能匹配了

如何构造?
如果两个位置匹配,要么这两个位置相等,要么为\(*\)

相等为0,容易想到减法
存在\(*\)就为0,容易想到*就表示0,然后乘起来

就成了这个样子:
\[\sum\limits_{i=1}^{len} (A_i - B_i)^2 * A_i * B_i\]

将其展开成为三个乘积相加的形式
我们将A串翻转,就可以三次fft计算了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<complex>
#include<cstring>
#include<algorithm>
#define eps 1e-9
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 1200005,maxm = 100005,INF = 1000000000;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
const double pi = acos(-1);
struct E{double r,i;E(){}E(double a,double b):r(a),i(b){}E operator =(const int& b){r = b; i = 0;return *this;}
};
inline E operator +(const E& a,const E& b){return E(a.r + b.r,a.i + b.i);
}
inline E operator -(const E& a,const E& b){return E(a.r - b.r,a.i - b.i);
}
inline E operator *(const E& a,const E& b){return E(a.r * b.r - a.i * b.i,a.r * b.i + b.r * a.i);
}
inline E operator *=(E& a,const E& b){return (a = a * b);
}
inline E operator /(E& a,const double& b){return E(a.r / b,a.i / b);
}
inline E operator /=(E& a,const double& b){return (a = a / b);
}
int n,m,L,R[maxn];
E A[maxn],B[maxn];
void fft(E* a,int f){for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);for (int i = 1; i < n; i <<= 1){E wn(cos(pi / i),f * sin(pi / i));for (int j = 0; j < n; j += (i << 1)){E w(1,0);for (int k = 0; k < i; k++,w *= wn){E x = a[j + k],y = w * a[j + k + i];a[j + k] = x + y; a[j + k + i] = x - y;}}}if (f == -1) for (int i = 0; i < n; i++) a[i] /= n;
}
char P[maxn],T[maxn];
int len,lm,ans[maxn],ansi;
double C[maxn];
void solve(){int tmp;for (int i = 0; i < n; i++) A[i] = B[i] = 0;for (int i = 0; i < len; i++){if (P[i] != '*'){tmp = (P[i] - 'a' + 1);A[i] = tmp * tmp * tmp;}}for (int i = 0; i < lm; i++){if (T[i] != '*'){tmp = (T[i] - 'a' + 1);B[i] = tmp;}}fft(A,1); fft(B,1);for (int i = 0; i < n; i++) A[i] *= B[i];fft(A,-1);for (int i = 0; i < n; i++) C[i] = floor(A[i].r + 0.5);for (int i = 0; i < n; i++) A[i] = B[i] = 0;for (int i = 0; i < len; i++){if (P[i] != '*'){tmp = (P[i] - 'a' + 1);A[i] = tmp * tmp;}}for (int i = 0; i < lm; i++){if (T[i] != '*'){tmp = (T[i] - 'a' + 1);B[i] = tmp * tmp;}}fft(A,1); fft(B,1);for (int i = 0; i < n; i++) A[i] *= B[i];fft(A,-1);for (int i = 0; i < n; i++) C[i] -= 2 * floor(A[i].r + 0.5);for (int i = 0; i < n; i++) A[i] = B[i] = 0;for (int i = 0; i < len; i++){if (P[i] != '*'){tmp = (P[i] - 'a' + 1);A[i] = tmp;}}for (int i = 0; i < lm; i++){if (T[i] != '*'){tmp = (T[i] - 'a' + 1);B[i] = tmp * tmp * tmp;}}fft(A,1); fft(B,1);for (int i = 0; i < n; i++) A[i] *= B[i];fft(A,-1);for (int i = 0; i < n; i++) C[i] += floor(A[i].r + 0.5);
}
int main(){len = read(); lm = read();scanf("%s",P);scanf("%s",T);for (int i = 0; i < (len >> 1); i++) swap(P[i],P[len - i - 1]);m = len + lm - 2;for (n = 1; n <= m; n <<= 1) L++;for (int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));solve();for (int i = 0; i <= m; i++){if (fabs(C[i]) < eps && i - len + 2 > 0 && i - len + 2 <= lm - len + 1){ans[++ansi] = i - len + 2;}}printf("%d\n",ansi);for (int i = 1; i <= ansi; i++) printf("%d ",ans[i]);return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8759425.html

BZOJ4259 残缺的字符串 【fft】相关推荐

  1. P4173 残缺的字符串 FFT匹配含有通配符的字符串

    传送门 文章目录 题意: 思路: 题意: 给你两个长度为m,nm,nm,n的串a,ba,ba,b,问你bbb串中每个长度为mmm的连续字串能否与aaa完全匹配,其中含有通配符∗*∗,输出每个位置的开头 ...

  2. BZOJ 4259: 残缺的字符串 [FFT]

    4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...

  3. 【BZOJ】4259: 残缺的字符串 FFT

    [题意]给定长度为m的匹配串B和长度为n的模板串A,求B在A中出现多少次.字符串仅由小写字母和通配符" * "组成,其中通配符可以充当任意一个字符.n<=3*10^5. [算 ...

  4. [BZOJ4259]残缺的字符串

    Description: 给定两个带通配符的串,求可能出现几次匹配,以及这些匹配位置 Hint: \(n \le 3*10^5\) Solution: 定义匹配函数 \(P(x)=\sum_{i=x} ...

  5. 【BZOJ4259】残缺的字符串

    题面 1684 -- [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现 ...

  6. 洛谷 - P4173 残缺的字符串(多项式匹配字符串-NTT)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串 sss 和一个长度为 mmm 的字符串 ttt,都含有通配符 '*',现在问字符串 ttt 可以匹配字符串 nnn 的哪些位置 题目分析 ...

  7. P4173 残缺的字符串

    P4173 残缺的字符串 题意: 有A,B两个串,每个串都有通配符,问A为模板串,对于 B 的每一个位置 i,从这个位置开始连续 m 个字符形成的子串是否可能与 A 串完全匹配? 题解: 我们定义两个 ...

  8. 洛谷P4173:残缺的字符串(FFT、通配符匹配)

    解析 通配符匹配的经典题. 设单词串为 AAA,文章串为 BBB. 把 AAA 翻转一下,判断问题就能转化为一个卷积的形式: F(p)=&i=0m−1match(Ai+1,Bp−i)F(p)= ...

  9. ●Codevs 4158 残缺的字符串

    题链: http://codevs.cn/problem/4158/ 题解: FFT. 定义两个相同长度的字符串s1,s2的距离为 $$dis(s1,s2)=\sum_{i=0}^{len-1}(s1 ...

  10. LGP4173残缺的字符串

    题解 由于有通配符,所以$kmp$失效了: 将通配符看成0,其余字符看成互不相同的数字,$A,B$串对应得到$a,b$数组; 定义: $f(p) = \sum_{i=0}^{m-1} a_{i}b_{ ...

最新文章

  1. 【Flutter】Dart 数据类型 字符串类型 ( 字符串定义 | 字符串拼接 | 字符串 API 调用 )
  2. .NET 缓存的设计
  3. linux电视改安卓,mstar安卓智能电视方案源代码常用修改
  4. 《视频直播技术详解》系列之三:处理
  5. 十五、类与封装的概念
  6. 通过css裁切图片为菱形图片
  7. PL/SQL Developer 12.0下载及汉化
  8. matlab erf erfi,误差函数
  9. Code3Kingdom - Tech Support
  10. Python基础知识点回顾
  11. 安装双系统/误删导致原来的引导分区中的boot丢失的解决方案
  12. 关于软件快捷方式显示异常,任务栏小图标模糊的解决方案
  13. 嵌入式linux编程开发必备知识
  14. 【计算机系统1】2 LC-3机器码编程实验
  15. 华硕Android原始密码,华硕路由器默认密码是多少?ASUS路由器初始密码介绍
  16. 怀孕期间各个月注意事项
  17. TCP 协议面试灵魂 12 问(二)
  18. 古老 IP 新玩法,盘点传统文化出圈秘籍
  19. 命令行 修复系统_让我们修复旧的命令行
  20. css 毛玻璃_我写CSS的常用套路(附demo的效果实现与源码)

热门文章

  1. usaco1.5.3(sprime)
  2. 深入理解 ASP.NET 动态控件 (Part 1 - 感性认识)
  3. vue中this.$set的用法
  4. Vue之.sync 修饰符详解
  5. 恢复误删文件 Windows File Recovery
  6. 17. 合并两个排序的链表(C++版本)
  7. Vmware使用net模式共享虚拟机linux IP
  8. Ubuntu18环境下安装ROS
  9. python策略模式包含角色_Python 之策略模式
  10. java包资源_Java获取jar包以外资源的方法