[4173] Luo Gu incomplete string (to regain FFT)

Click here to see the problem surface

Generally meaning of the questions: a length \ (n-\) string \ (A \) and a length \ (m \) string \ (B \) , wherein some characters '*' may be arbitrary character match. Seeking \ (B \) in all the positions that satisfy the condition, so that starting from this position continuously \ (n-\) string of characters and can \ (A \) exact match.

Foreword

Prior has been on the \ (FFT \) algorithm do not understand, was feeling a little math standards have improved, then I went to re-read all over \ (FFT \) principle, suddenly found to generally understand ......

This question is the title of the original \ (A \) length of \ (m \) , \ (B \) of length \ (n-\) , for personal habits, the \ (n-\) and \ (m \) exchange a moment, becomes \ (a \) of length \ (n-\) , \ (B \) length of \ (m \) .

Also for personal habits, also I \ (n-\) and \ (m \) are each a Save \ (1 \) , then \ (A \) in the subscript \ (0 \ n-SIM \) , \ ( B \) in the subscript \ (0 \ SIM m \) , since the subject of the request from the subscript \ (1 \) begins, the final answer in turn added \ (1 \) .

I hope to understand.

\ (FFT \) and string matching

\ (FFT \) and string matching, seemingly without any contact, but in fact of great use.

For example, this question, we can first be converted into a digital character, 'a' ~ 'z' each correspond \ (. 1 \ SIM 26 is \) , and the '*' on the use of \ (0 \) is represented.

Is not considered '*', then if you want to compare two characters \ (x, y \) matches, it is clear we can see if \ (the y-the X-= \) , namely \ (the XY = 0 \) , two characters match, and if \ (XY ≠ 0 \) , then the two characters do not match.

In other words, we are here to \ (xy \) seen as a match is found, the matching value \ (0 \) indicates a match, not \ (0 \) represents a mismatch.

However, if you want to compare two strings match, but it can not simply put on every \ (xy \) value added together to determine whether \ (0 \) , because (xy \) \ can be positive or negative, plus together they might cancel each other out to \ (0 \) .

How to do?

Remove the negative sign is not on line yet? First, the match will think of value to \ (| the XY | \) , but this does not seem good operation.

However, if instead \ ((the XY) ^ 2 \) , it seems very feasible way.

In summary, if you want to compare two equal-length string exact match, we can find for every \ ((the XY) ^ 2 \) , and then summed, and if the last is \ (0 \) , indicating exact match, or not match the description.

That there has been '*' it?

Since the '*' can match any character, and above we decide to use \ (0 \) to represent '' * ', and the definition of exact match is matching value \ (0 \) .

So, we can match the value to \ (the XY (the XY) ^ 2 \) , if the sum equation is \ (0 \) , it shows an exact match.

Push formula

Suppose we now determined from \ (B \) first \ (I \) bits starting continuous \ (n-\) characters whether the \ (A \) exact match.

It is to ask:

\[\sum_{k=0}^nA_kB_{i+k}(A_k-B_{i+k})^2\]

Obtained by unraveling:

\[\sum_{k=0}^n(A_k^3B_{i+k}-2A_k^2B_{i+k}^2+A_kB_{i+k}^3)\]

Consider setting \ (T_ {} = K NK A_ {} \) , i.e. \ (A \) of Backward string, the original formula is equivalent to:

\[\sum_{k=0}^n(T_{n-k}^3B_{i+k}-2T_{n-k}^2B_{i+k}^2+T_{n-k}B_{i+k}^3)\]

Then we can find a very magical is: each pair of multiplying the sum of the index of the item are \ (the n-i + \) , in \ (i \) is constant is a fixed value!

So, we can change that equation into a convolution form, namely:

\[\sum_{x+y=n+i}(T_{x}^3B_{y}-2T_{x}^2B_{y}^2+T_{x}B_{y}^3)\]

That way, as long as \ (T, T ^ 2, T ^ 3, B, B ^ 2, B ^ 3 \) six polynomials are made \ (the DFT \) , performed after the calculation, do \ ( IDFT \) , you can get a new polynomial \ (P \) .

From \ (B \) of the \ (I \) consecutive bits starting \ (\ n-) characters can and \ (A \) exact match, if and only if \ (P \) first \ (n + I \) coefficient term of \ (0 \) .

This is done on this question.

Code

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 300000
#define LL long long
#define DB double
using namespace std;
int n,m,a[4*N+5],b[4*N+5];char s[N+5];
template<int SZ> class Poly
{
    private:
        int P,L,R[4*N+5];DB Pi;
        struct node
        {
            DB x,y;I node(Con DB& a=0,Con DB& b=0):x(a),y(b){}
            I node operator + (Con node& o) Con {return node(x+o.x,y+o.y);}
            I node operator - (Con node& o) Con {return node(x-o.x,y-o.y);}
            I node operator * (Con node& o) Con {return node(x*o.x-y*o.y,x*o.y+y*o.x);}
        }A[4*N+5],A2[4*N+5],A3[4*N+5],B[4*N+5],B2[4*N+5],B3[4*N+5];
        I void T(node *s,CI op)
        {
            RI i,j,k;node U,S,x,y;for(i=0;i^P;++i) i<R[i]&&(U=s[i],s[i]=s[R[i]],s[R[i]]=U,0);
            for(i=1;i^P;i<<=1) for(U=node(cos(Pi/i),op*sin(Pi/i)),j=0;j^P;j+=i<<1)
                for(S=node(1,0),k=0;k^i;++k,S=S*U) s[j+k]=(x=s[j+k])+(y=S*s[i+j+k]),s[i+j+k]=x-y;
        }
    public:
        I Poly() {Pi=acos(-1);}
        Tp I void FFT(CI n,CI m,Ty *a,Ty *b)
        {
            RI i;P=1,L=0;W(P<=n+m) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
            for(i=0;i<=n;++i) A[i]=a[i],A2[i]=A[i]*A[i],A3[i]=A[i]*A2[i];//记录多项式
            for(i=0;i<=m;++i) B[i]=b[i],B2[i]=B[i]*B[i],B3[i]=B[i]*B2[i];//记录多项式
            T(A,1),T(A2,1),T(A3,1),T(B,1),T(B2,1),T(B3,1);//DFT
            for(i=0;i^P;++i) A[i]=A3[i]*B[i]-node(2)*A2[i]*B2[i]+A[i]*B3[i];//运算
            for(T(A,-1),i=0;i<=m;++i) a[i]=A[i].x/P+0.5;//IDFT
        }
};Poly<N> P;
int main()

    RI i,t=0;scanf("%d%d",&n,&m),--n,--m;
    for(scanf("%s",s),i=0;i<=n;++i) a[n-i]=s[i]=='*'?0:(s[i]&31);//注意A串取倒串
    for(scanf("%s",s),i=0;i<=m;++i) b[i]=s[i]=='*'?0:(s[i]&31);
    for(P.FFT(n,m,a,b),i=0;i<=m-n;++i) t+=!a[n+i];printf("%d\n",t);//统计个数
    for(i=0;i<=m-n;++i) !a[n+i]&&printf("%d ",i+1);return 0;//输出合法位置
}

Guess you like

Origin www.cnblogs.com/chenxiaoran666/p/Luogu4173.html