2017-2018 ACM-ICPC, Asia Daejeon Regional Contest

H - Rock Paper Scissors(FFT)

给序列A,B,比划石头剪刀布,问序列B去匹配A中的哪一个字段,能够使胜的场数最多。序列长度为十万。

可以假定A出剪刀,B出石头胜,则把A中剪刀都置成1,B中石头都置成1,其他置成0,那么 i = 0 l e n A s t a r t P o s + i B i

#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
const int maxn = 200000 + 5;


struct data
{
    double x, y;
    data()
    {
        x = y = 0;
    }
    data(double x0, double y0)
    {
        x = x0, y = y0;
    }
    data operator+(const data &a)const
    {
        return data(x + a.x, y + a.y);
    }
    data operator-(const data &a)const
    {
        return data(x - a.x, y - a.y);
    }
    data operator*(const data &a)const
    {
        return data(x * a.x - y * a.y, x * a.y + y * a.x);
    }
};
void fft(data*a, int n, int f) {
    int i, j, k;
    for(i = j = 0; i < n; ++ i) {
        if(i > j) swap(a[i], a[j]);
        for(k = n>>1; (j ^= k) < k; k >>= 1);
    }
    for(i = 1; i < n; i <<= 1) {
        data wn(cos(pi/i), f*sin(pi/i));
        for(j = 0; j < n; j += i<<1) {
            data w(1, 0);
            for(k = 0; k < i; ++ k, w=w*wn) {
                data x = a[j+k], y = w*a[i+j+k];
                a[j+k] = x+y; a[i+j+k] = x-y;
            }
        }
    }
    if(-1 == f) for(i = 0; i < n; ++ i) a[i].x /= n;
}

char s1[maxn], s2[maxn];
data a[maxn*2], b[maxn*2];
int ans1[maxn*2], ans2[maxn*2], ans3[maxn*2];
int n, m;

int main()
{

    scanf("%d%d", &n, &m);
    scanf("%s", s1);
    scanf("%s", s2);
    reverse(s2, s2+m);

    int len = 1;
    while(len < n + m)  len <<= 1;
    //s2 rock -> s1 scissors
    for(int i = 0; i < len; i++)    a[i].x = b[i].x = a[i].y = b[i].y = 0;
    for(int i = 0; i < m; i++)  b[i].x = (s2[i] == 'R');
    for(int i = 0; i < n; i++)  a[i].x = (s1[i] == 'S');
    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 = m-1; i < m-1+n; i++)    ans1[i-m+1] = int(a[i].x +0.5);
    //s2 scissors -> s1 paper
    for(int i = 0; i < len; i++)    a[i].x = b[i].x = a[i].y = b[i].y = 0;
    for(int i = 0; i < m; i++)  b[i].x = (s2[i] == 'S');
    for(int i = 0; i < n; i++)  a[i].x = (s1[i] == 'P');
    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 = m-1; i < m-1+n; i++)    ans2[i-m+1] = int(a[i].x +0.5);
    //s2 paper -> s1 rock
    for(int i = 0; i < len; i++)    a[i].x = b[i].x = a[i].y = b[i].y = 0;
    for(int i = 0; i < m; i++)  b[i].x = (s2[i] == 'P');
    for(int i = 0; i < n; i++)  a[i].x = (s1[i] == 'R');
    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 = m-1; i < m-1+n; i++)    ans3[i-m+1] = int(a[i].x +0.5);
    int ans = 0;
    for(int i = 0; i < n; i++)  ans = max(ans, ans1[i]+ans2[i]+ans3[i]);
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_29556211/article/details/80427068