GYM 101667H Rock Paper Scissors(FFT)

题意:给你一个串a,是有R,S,P(石头剪刀布)构成的,然后还有一个序列b是你的出牌顺序,但你可以跳过机器的前x个出牌,从x+1开始出,问你最多赢几次

思路:好烦啊,这个题下午一直不会做,感觉和之前学弟将的一个模糊匹配的很像,但好像也不怎么像,挂机一下午。

  这个题其实是利用了卷积的性质,我们先考虑单独的每一个字母,因为我们在卷积的时候不能牵扯其他的字符,如果有其他的字符,就类似于模糊匹配了,那是我们只是用FFT加速多项式乘法,而这道题的FFT其实是用FFT算出对于(FFT后的)第i个位置,我们字符匹配后所得到的价值,所以我们把三种字符都加起来,然后取max,其实不是很难理解

代码:(逆fft的时候忘记除n,找了很久,很久不写FFT,基本忘得差不多了)

#include <bits/stdc++.h>
using namespace std;


const int N = 400005;
const double PI=acos(-1.0);
struct cp
{
    double r,i;
    cp(){}
    cp(double _r,double _i)
    {
        r=_r;i=_i;
    }
    cp operator +(const cp a)const
    {
        return cp(a.r+r,a.i+i);
    }
    cp operator -(const cp a)const
    {
        return cp(r-a.r,i-a.i);
    }
    cp operator *(const cp a)const
    {
        return cp(r*a.r-i*a.i,r*a.i+i*a.r);
    }
    cp conj()
    {
        return cp(r,-i);
    }
};

int n=1,m;
cp f[N],g[N],omg[N],inv[N];
void FFT_init(){
    for(int i=0;i<n;i++){
        omg[i]=cp(cos(2*PI*i/n),sin(2*PI*i/n));
        inv[i]=omg[i].conj();
    }
}
void fft(cp *a,cp *omg){
    int lim=0;
    while((1 << lim) < n) lim++;
    for(int i=0;i<n;i++){
        int t=0;
        for(int j=0;j<lim;j++)
            if(i >> j&1) t |= 1 << (lim - j - 1);
        if(i<t) swap(a[i],a[t]);
    }
    for(int l=2;l<=n;l*=2){
        int m=l/2;
        for(cp *p=a;p!=a+n;p+=l){
            for(int i=0;i<m;i++){
                cp t=omg[n/l*i]*p[m+i];
                p[m+i]=p[i]-t;
                p[i]=p[i]+t;
            }
        }
    }
}

int res[N],sum[N];
char a[N],b[N];
int lena,lenb;
void solve(char c)
{
    for(int i=0;i<lena;i++){
        if(a[i]==c)f[i].r=1;
        else f[i].r=0;
        f[i].i=0;
    }
    for(int i=lena;i<n;i++){
        f[i].r=0;f[i].i=0;
    }
    for(int i=0;i<lenb;i++){
        if(b[i]==c)g[i].r=1;
        else g[i].r=0;
        g[i].i=0;
    }
    for(int i=lenb;i<n;i++){
        g[i].r=0;g[i].i=0;
    }
    fft(f,omg),fft(g,omg);
    for(int i=0;i<n;i++)f[i]=f[i]*g[i];
    fft(f,inv);
    for(int i=0;i<n;i++){
        sum[i]=(int)(f[i].r/n+0.5);
    }
    for(int i=0;i<n;i++){
        res[i]+=sum[i];
    }
}
int main()
{
    scanf("%d%d",&lena,&lenb);
    scanf("%s%s",a,b);
    for(int i=0;i<lena;i++){
        if(a[i]=='S')a[i]='R';
        else if(a[i]=='R')a[i]='P';
        else if(a[i]=='P')a[i]='S';
    }
    reverse(b,b+lenb);
    while(n<lena*2||n<lenb*2)n<<=1;
    FFT_init();
    solve('S');
    solve('R');
    solve('P');
    int ans=0;
    for(int i=lenb-1;i<lena+lenb-1;i++){
        ans=max(ans,res[i]);
    }
    printf("%d\n",ans);
    return 0;
}
/*
12 4
RSPPSSSRRPPR
RRRR
*/

 

posted @ 2018-10-04 19:51  啦啦啦天啦噜  阅读(471)  评论(0编辑  收藏  举报