FFT(Rock Paper Scissors Gym - 101667H)

题目链接:https://vjudge.net/problem/Gym-101667H

题目大意:首先给你两个字符串,R代表石头,P代表布,S代表剪刀,第一个字符串代表第一个人每一次出的类型,第二个字符串代表第二个人每一次出的类型,问怎么控制第二个人开始的地方,能使得第二个人获胜的几率最大,然后输出最多获胜的局数。

具体思路:FFT,我们首先把第二个字符串每一个类型全部转换成他的对立面,比如说石头就转换成布,布就转换成剪刀,剪刀就转换成石头,然后我们就直接用第二个字符串去匹配就可以了。

匹配的时候,我们是将三个分着进行的,先求从每一个位置开始子串的最大匹配量,三个分别求好之后,我们就遍历一下每一个位置看一下那个位置的最大匹配量就可以了。

AC代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<stdio.h>
  7 using namespace std;
  8 # define ll long long
  9 const double PI = acos(-1.0);
 10 const int maxn = 4e5+100;
 11 struct complex
 12 {
 13     double r,i;
 14     complex(double _r = 0,double _i = 0)
 15     {
 16         r = _r;
 17         i = _i;
 18     }
 19     complex operator +(const complex &b)
 20     {
 21         return complex(r+b.r,i+b.i);
 22     }
 23     complex operator -(const complex &b)
 24     {
 25         return complex(r-b.r,i-b.i);
 26     }
 27     complex operator *(const complex &b)
 28     {
 29         return complex(r*b.r-i*b.i,r*b.i+i*b.r);
 30     }
 31 };
 32 void change(complex y[],int len)
 33 {
 34     int i,j,k;
 35     for(i = 1, j = len/2; i < len-1; i++)
 36     {
 37         if(i < j)
 38             swap(y[i],y[j]);
 39         k = len/2;
 40         while( j >= k)
 41         {
 42             j -= k;
 43             k /= 2;
 44         }
 45         if(j < k)
 46             j += k;
 47     }
 48 }
 49 void fft(complex y[],int len,int on)
 50 {
 51     change(y,len);
 52     for(int h = 2; h <= len; h <<= 1)
 53     {
 54         complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
 55         for(int j = 0; j < len; j += h)
 56         {
 57             complex w(1,0);
 58             for(int k = j; k < j+h/2; k++)
 59             {
 60                 complex u = y[k];
 61                 complex t = w*y[k+h/2];
 62                 y[k] = u+t;
 63                 y[k+h/2] = u-t;
 64                 w = w*wn;
 65             }
 66         }
 67     }
 68     if(on == -1)
 69         for(int i = 0; i < len; i++)
 70             y[i].r /= len;
 71 }
 72 complex x1[maxn],x2[maxn];
 73 char str1[maxn],str2[maxn];
 74 int sum[maxn],len,len1,len2,ans[maxn];
 75 void cal(char tmp)
 76 {
 77     for(int i=0; i<len1; i++)
 78     {
 79         x1[i]=complex(str1[i]==tmp,0);
 80     }
 81     for(int i=len1; i<len; i++)
 82     {
 83         x1[i]=complex(0,0);
 84     }
 85     for(int i=0; i<len2; i++)
 86     {
 87         x2[i]=complex(str2[len2-i-1]==tmp,0);//记得要将第二个字符串进行翻转。
 88     }
 89     for(int i=len2; i<len; i++)
 90     {
 91         x2[i]=complex(0,0);
 92     }
 93     fft(x1,len,1);
 94     fft(x2,len,1);
 95     for(int i=0; i<len; i++)
 96     {
 97         x1[i]=x1[i]*x2[i];
 98     }
 99     fft(x1,len,-1);
100     for(int i=0; i<len; i++)
101     {
102         sum[i]=(int)(x1[i].r+0.5);
103     }
104     for(int i=0; i<len; i++)
105     {
106         ans[i]+=sum[i];
107     }
108 }
109 int main()
110 {
111     int n,m;
112     scanf("%d %d",&n,&m);
113     scanf("%s",str1);
114     scanf("%s",str2);
115     len=1;
116     len1=strlen(str1);
117     len2=strlen(str2);
118     while(len<len1*2||len<len2*2)
119         len<<=1;
120     for(int i=0; i<len1; i++)
121     {
122         if(str1[i]=='R')
123         {
124             str1[i]='P';
125         }
126         else if(str1[i]=='P')
127         {
128             str1[i]='S';
129         }
130         else if(str1[i]=='S')
131         {
132             str1[i]='R';
133         }
134     }
135     cal('P');
136     cal('S');
137     cal('R');
138     int maxx=0;
139     for(int i=len2-1; i<len1+len2-1; i++)//注意起点是第二个字符串的长度对应的下标,也就是冷len2-1.
140     {
141         maxx=max(maxx,ans[i]);
142     }
143     printf("%d\n",maxx);
144     return 0;
145 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10301962.html