H - Rock Paper Scissors(FFT)
给序列A,B,比划石头剪刀布,问序列B去匹配A中的哪一个字段,能够使胜的场数最多。序列长度为十万。
可以假定A出剪刀,B出石头胜,则把A中剪刀都置成1,B中石头都置成1,其他置成0,那么
#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;
}