洛谷 - P4173 残缺的字符串(多项式匹配字符串-NTT)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 - P4173 残缺的字符串(多项式匹配字符串-NTT)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出一个长度为 n n n 的字符串 s s s 和一个长度为 m m m 的字符串 t t t,都含有通配符 ‘*’,现在问字符串 t t t 可以匹配字符串 n n n 的哪些位置
题目分析:模糊匹配的模板题,这里只记录一下公式,具体推导博客详见:
https://www.luogu.com.cn/blog/Ebola-Emperor/solution-p4173
先放两个公式:
设原模式串为 A A A,匹配串 B B B, A A A 的翻转 S S S
P ( x ) P(x) P(x) 为全匹配函数,若 P ( x ) = 0 P(x)=0 P(x)=0 则称 B B B 以第 x x x 位结束的连续 m m m 位,与 A A A 完全匹配
普通的单模式串匹配: P ( x ) = T + f ( x ) − f ( x − m ) − 2 g ( x ) P(x)=T+f(x)-f(x-m)-2g(x) P(x)=T+f(x)−f(x−m)−2g(x)
其中 T = ∑ i = 0 m − 1 S ( i ) 2 T=\\sum\\limits_{i=0}^{m-1}S(i)^2 T=i=0∑m−1S(i)2, f ( x ) = ∑ i = 0 x B ( i ) 2 f(x)=\\sum\\limits_{i=0}^{x}B(i)^2 f(x)=i=0∑xB(i)2, g ( x ) = ∑ i + j = x S ( i ) B ( j ) g(x)=\\sum\\limits_{i+j=x}S(i)B(j) g(x)=i+j=x∑S(i)B(j)
伪代码:
void FFT_Match(char *s1,char *s2,int m,int n)
{
for(int i=0;i<m;i++) A[i].r=s1[i]-'a'+1;
for(int i=0;i<n;i++) B[i].r=s2[i]-'a'+1;
reverse(A,A+m);double T=0;
for(int i=0;i<m;i++) T+=A[i].r*A[i].r;
f[0]=B[0].r*B[0].r;
for(int i=1;i<n;i++) f[i]=f[i-1]+B[i].r*B[i].r;
FFT(A,len,1);FFT(B,len,1);
for(int i=0;i<len;i++) g[i]=A[i]*B[i];
FFT(g,len,-1);
for(int x=m-1;x<n;x++)
{
double P=T+f[x]-f[x-m]-2*g[x].r;
if(fabs(P)<eps) printf("%d ",x-m+2);
}
}
带通配符的单模式串匹配: P ( x ) = ∑ i + j = x S ( i ) 3 B ( j ) + ∑ i + j = x S ( i ) B ( j ) 3 − 2 ∑ i + j = x S ( i ) 2 B ( j ) 2 P(x)=\\sum\\limits_{i+j=x}S(i)^3B(j)+\\sum\\limits_{i+j=x}S(i)B(j)^3-2\\sum\\limits_{i+j=x}S(i)^2B(j)^2 P(x)=i+j=x∑S(i)3B(j)+i+j=x∑S(i)B(j)3−2i+j=x∑S(i)2B(j)2
伪代码:
void FFT_match(char *s1,char *s2,int m,int n)
{
reverse(ss1,ss1+m);
for(int i=0;i<m;i++) A[i]=(s1[i]!='*')?(s1[i]-'a'+1):0;
for(int i=0;i<n;i++) B[i]=(s2[i]!='*')?(s2[i]-'a'+1):0;
for(int i=0;i<len;i++) a[i]=Comp(A[i]*A[i]*A[i],0),b[i]=Comp(B[i],0);
FFT(a,len,1);FFT(b,len,1);
for(int i=0;i<len;i++) P[i]=P[i]+a[i]*b[i];
for(int i=0;i<len;i++) a[i]=Comp(A[i],0),b[i]=Comp(B[i]*B[i]*B[i],0);
FFT(a,len,1);FFT(b,len,1);
for(int i=0;i<len;i++) P[i]=P[i]+a[i]*b[i];
for(int i=0;i<len;i++) a[i]=Comp(A[i]*A[i],0),b[i]=Comp(B[i]*B[i],0);
FFT(a,len,1);FFT(b,len,1);
for(int i=0;i<len;i++) P[i]=P[i]-a[i]*b[i]*Comp(2,0);
FFT(P,len,-1);
for(int i=m-1;i<n;i++) if(fabs(P[i].r)<=1e-7) printf("%d ",i-m+2);
}
本题代码:(NTT实现)
// Problem: P4173 残缺的字符串
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4173
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
const int mod=998244353,G=3,Gi=332748118;
int n,m,limit = 1,L,r[N<<2],res[N<<2];
LL a[N<<2],b[N<<2],P[N<<2],A[N<<2],B[N<<2];
inline LL fastpow(LL a, LL k) {
LL base = 1;
while(k) {
if(k & 1) base = (base * a ) % mod;
a = (a * a) % mod;
k >>= 1;
}
return base % mod;
}
inline void NTT(LL *A, int type) {
for(以上是关于洛谷 - P4173 残缺的字符串(多项式匹配字符串-NTT)的主要内容,如果未能解决你的问题,请参考以下文章