题目链接: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 ",maxx); 144 return 0; 145 }