fft字符串匹配 Rock Paper Scissors Gym - 101667H

第一次见到这种题,没想到fft还能这么用,补体的时候换了好多个版本,wa了差不多一整页才过,有点难受。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn = 1e6 + 7;
const double pi = acos(-1.0);
int sum[maxn];
int res[maxn];
int rev[maxn];

struct cp
{
    double r, i;
    cp(double _r = 0.0, double _i = 0.0)
    {
        r = _r;
        i = _i;
    }
    cp operator +(const cp &p) const
    {
        cp xx;
        xx.i=i + p.i;
        xx.r=r + p.r;
        return xx;
    }
    cp operator -(const cp &p)const
    {
        cp xx;
        xx.i=i - p.i;
        xx.r=r - p.r;
        return xx;
    }
    cp operator *(const cp &p) const
    {
        cp xx;
        xx.r = r * p.r +  - i * p.i;
        xx.i = r  * p.i + i * p.r;
        return xx;
    }
};

void change(cp y[], int len)
{
    for(int i = 1, j = len / 2; i < len - 1; i++)
    {
        if(i < j) swap(y[i], y[j]);
        int k = len / 2;
        while(j >= k)
        {
            j -= k;
            k >>= 1;
        }
        if(j < k)
            j += k;
    }
}
void fft(cp y[], int len, int op)
{
    change(y, len);
    for(int h = 2; h <= len; h<<=1)
    {
        cp wn(cos(-op * 2 * pi / h), sin(-op* 2 * pi / h));
        for(int j = 0; j < len; j += h)
        {
            cp w(1, 0);
            for(int k = j; k < j + h / 2; k++)
            {
                cp u = y[k];
                cp t = w * y[k + h / 2];
                //printf("%f %f %f %f %f %f\n", y[k].r,  y[k].h, w.r, w.i, t.r, t.i);
                y[k] = u + t;
                y[k + h/ 2] = u - t;
                w = w * wn;
            }
        }
    }
    if(op == -1)
        for(int i = 0; i < len; i++)
        y[i].r /= len;
}
cp a[maxn], b[maxn];
char s[maxn], p[maxn];

void conv(char w, int n,int m)
{
    int len = 1;
    while(len < n * 2 || len < m * 2) len<<=1;
    for(int i = 0; i < n; i++)
    {
        if(s[i] == w) a[i] = cp(1, 0);
        else a[i] = cp(0, 0);
    }
    for(int i = n; i < len; i++)
    {
        a[i] = cp(0, 0);
    }
    for(int i = 0; i < m; i++)
    {
        if(p[i] == w) b[i] = cp(1, 0);
        else b[i] = cp(0, 0);
    }
    for(int i = m; i < len; i++)
        b[i] = cp(0, 0);
    fft(a, len, 1);
    fft(b, len, 1);
    for(int i = 0; i < len; i++)
        a[i] = a[i] * b[i];
    fft(a, len, -1);
    for(int i = 0; i < len; i++)
        sum[i] += (int)(a[i].r + 0.5);
}
int main()
{
    int len1, len2;
    scanf("%d%d", &len1, &len2);
    scanf("%s%s", s, p);
    for(int i = 0; i < len2; i++)
    {
        if(p[i] == 'S') p[i] = 'P';
        else if(p[i] == 'P') p[i] = 'R';
        else if(p[i] == 'R') p[i] = 'S';
    }
    reverse(p, p + len2);
    conv('S' ,len1, len2);
    conv('R', len1, len2);
    conv('P', len1, len2);
    int ans = -0x3f3f3f3f;
    for(int i = len2 - 1; i < len1 + len2 - 1; i++)
        ans = max(ans, sum[i]);
    printf("%d\n", ans);
    return 0;

}

发布了40 篇原创文章 · 获赞 13 · 访问量 854

猜你喜欢

转载自blog.csdn.net/weixin_43891021/article/details/102562607