topic
meaning of the title
Give the order of two pieces of rock-paper-scissors
and
,in
To be shorter, now let you put
Past
lean on a certain position, so that after leaning,
can win
The maximum number of subsections.
As shown in the figure:
answer
This problem is very typical FFT, first of all we put Change the sequence to a sequence it can win , that is, in sequence corresponding to form 。
In this case, we only need to It is enough to find a paragraph with the greatest degree of matching, and the greatest degree of matching is the answer.
To match, we put
Inverted, denoted as
, we imagine the process of doing convolution and
find the first number in the new convolution sequence
The value of the positions is equal to
and
The sum of the products of the corresponding positions of the sequence.
To solve this problem using convolution, we split the problem into 3 parts, i.e. consider separately At the same time, the maximum matching degree, and finally the matching degree of the same position is added up.
code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
double pi = acos(-1.0);
struct complex{
double re,im;
complex(double r = 0.0,double i = 0.0):re(r),im(i){};
complex operator+(complex com){
return complex(re+com.re,im+com.im);
}
complex operator-(complex com){
return complex(re-com.re,im-com.im);
}
complex operator*(complex com){
return complex(re*com.re-im*com.im,re*com.im+im*com.re);
}
};
complex wn,wntmp;
void rader(complex arr[],int n){
int num = n-1;
for(int i = 0;i < n;++i){
int tn = n>>1;
while(num && num >= tn) num ^= tn,tn >>= 1;
num |= tn;
if(num > i) swap(arr[i],arr[num]);
}
}
void FFT(complex cs[],int n,int f){
rader(cs,n);
for(int s = 1;s < n;s <<= 1){
wn = complex(cos(f*2*pi/(s*2)),sin(f*2*pi/(s*2)));
for(int offset = 0;offset < n;offset += s<<1){
wntmp = complex(1.0,0.0);
for(int i = 0;i < s;++i){
complex u = cs[offset+i],v = cs[offset+i+s]*wntmp;
cs[offset+i] = u + v;
cs[offset+i+s] = u - v;
wntmp = wntmp * wn;
}
}
}
if(f == -1)
for(int i = 0;i < n;++i)
cs[i].re /= n;
}
int n,m;
const int maxn = 1e5+7;
char S[maxn],T[maxn];
int ans[maxn*4];
complex csA[maxn*4],csB[maxn*4];
#define pr(x) cout<<#x<<":"<<x<<endl
void solve(char c){
memset(csA,0,sizeof(csA));
memset(csB,0,sizeof(csB));
for(int i = 0;i < n;++i) csA[i] = complex(S[i]==c?1.0:0);
for(int i = 0;i < m;++i) csB[i] = complex(T[i]==c?1.0:0);
int len = 1;
while(len < n) len<<=1;
len <<= 1;
FFT(csA,len,1);
FFT(csB,len,1);
for(int i = 0;i < len;++i) csA[i] = csA[i]*csB[i];
FFT(csA,len,-1);
for(int i = m-1;i < len;++i) {
ans[i] += int(csA[i].re+0.5);
};
}
char big(char c){
if(c == 'R') return 'S';
if(c == 'S') return 'P';
if(c == 'P') return 'R';
}
int main(){
cin>>n>>m>>S>>T;
for(int i = 0;i < m/2;++i) swap(T[i],T[m-1-i]);
for(int i = 0;i < m;++i) T[i] = big(T[i]);
solve('P');
solve('S');
solve('R');
int mx = 0;
for(int i = 0;i < n+m+1;++i) mx = max(mx,ans[i]);
cout<<mx<<endl;
return 0;
}