zoukankan      html  css  js  c++  java
  • [Test1.11]-T1匹配 Matching

    Description:

    给定两个含小写字母、通配符的字符串 (S), (T)
    出于简化问题的考虑,这里的通配符只有"(?)"一种。它可以匹配任意一个字符。
    一个串 (T)(S)({pos}) 位置上出现,当且仅当:
    ∀1 ≤ i ≤ |T|, Spos+i 1 = Ti | Spos+i 1 =′?′ | Ti =′?′
    你的任务是:求 T 在 S 中的出现次数。

    数据范围:

    |T| ≤ |S| ≤ 2 × 1e5
    时限:3s
    空间:128mb

    Solution:

    solution

    代码:

    #include<iostream>
    #include<cstdio>
    #include<complex>
    #include<cstring>
    #define R register
    #define ll long long
    #define eps 1e-8
    #define is0(x) ((x) < eps && -(x) < eps)
    using namespace std;
    namespace IO
    {
    	template<class T>
    	void rea(T &x)
    	{
    		char ch=getchar();long long f(0);x = 0;
    		while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
    		while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    		x = f?-x:x;
    	}
    	template<class T>
    	T max(T a, T b){return (a>b?a:b);}
    	template<class T>
    	T min(T a, T b){return (a<b?a:b);}
    }
    const long long N = 600005;
    char s[N], t[N], pre[N];
    long long pos[N], tot, lens, lent, ans[N];
    complex<double>a[N], b[N], x[N], y[N];
    void init(long long k)
    {
    	long long len = 1<<k;
    	for(R long long i = 0; i < len; ++i)
    		pos[i] = (pos[i>>1]>>1)|((i&1)<<(k-1));
    }
    void fft(complex<double> *a, long long n, long long flag)
    {
    	for(R long long i = 0; i < n; ++i) if(i < pos[i]) swap(a[i], a[pos[i]]);
    	for(R long long len = 1; len < n; len *= 2)
    	{
    		complex<double> wx = complex<double>(cos(M_PI/len), flag*sin(M_PI/len));
    		for(R long long i = 0; i < n; i += len*2)
    		{
    			complex<double> w(1, 0);
    			for(R long long j = i; j < i+len; ++j)
    			{
    				complex<double> x = a[j];
    				complex<double> y = w*a[j+len];
    				a[j] = x+y;
    				a[j+len] = x-y;
    				w *= wx;
    			}
    		}
    	}
    	if(flag == -1) for(R long long i = 0; i < n; ++i) a[i] /= n;
    }
    void solve(long long flag, long long n)
    {
    	fft(x, n, 1);fft(y, n, 1);
    	for(R long long i = 0; i < n; ++i) x[i] *= y[i];
    	fft(x, n, -1);
    	for(R long long i = 0; i < n; ++i) ans[i] += (long long)(x[i].real()+0.5)*flag;
    }
    int main()
    {
    	freopen("matching.in","r",stdin);
    	freopen("matching.out","w",stdout);
    	scanf("%s%s", s, pre);
    	lens = strlen(s), lent = strlen(pre);
    	for(R long long i = 0; i < lent; ++i) t[i] = pre[lent-i-1];
    	for(R long long i = 0; i < lens; ++i) a[i] = (double)((s[i]=='?'?0 : s[i]-'a'+1));
    	for(R long long i = 0; i < lent; ++i) b[i] = (double)((t[i]=='?'?0 : t[i]-'a'+1));
    	long long P = 1, k = 0;
    	while(P <= lens+lent) P <<= 1, k++;
    	init(k);
    	for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i]*a[i], y[i] = b[i];
    	solve(1, P);
    	for(R long long i = 0; i < P; ++i) x[i] = a[i], y[i] = b[i]*b[i]*b[i];
    	solve(1, P);
    	for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i], y[i] = b[i]*b[i];
    	solve(-2, P);
    	for(R long long i = lent-1; i < lens; ++i) if(is0(ans[i])) tot++;
    	printf("%d
    ", tot);
    	return 0;
    }
    
  • 相关阅读:
    ZJOI2019二轮游记
    Luogu P5284 [十二省联考2019]字符串问题
    Luogu P5309 [Ynoi2012]D1T1
    Luogu P5292 [HNOI2019]校园旅行
    LOJ #6052. 「雅礼集训 2017 Day11」DIV
    Luogu P5279 [ZJOI2019]麻将
    LOJ #6060. 「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set
    Luogu P5283 [十二省联考2019]异或粽子
    Luogu P5290 [十二省联考2019]春节十二响
    Luogu P5285 [十二省联考2019]骗分过样例
  • 原文地址:https://www.cnblogs.com/heanda/p/12398591.html
Copyright © 2011-2022 走看看