2021年度训练联盟热身训练赛第四场 H - Rock Paper Scissors(字符串匹配,FFT)
整理的算法模板合集: ACM模板
点我看算法全家桶系列!!!
实际上是一个全新的精炼模板整合计划
2021年度训练联盟热身训练赛第四场 H - Rock Paper Scissors(字符串匹配,FFT)
Weblink
https://ac.nowcoder.com/acm/contest/13506/H
Problem
你和电脑玩剪刀石头布,给定一个电脑的出拳序列 sss 以及你的一个出拳序列 ttt ,你可以任意在电脑的出拳序列 sss 里选择一个位置开始比赛直到序列结束,问你最多能赢多少场。
12 4
RSPPSSSRRPPR
RRRR
3
Solution
SB题直接秒了
显然先转换为字符串匹配,即将字符串里, RRR 赢 SSS ,问我们能赢多少场,所以把电脑的出拳序列里所有的 SSS 换成 RRR ,P,SP,SP,S 同理,这样问题就可以转换为一个简单的字符串匹配了,然后考虑如何匹配,显然我们可以把三个分开来一个一个匹配这样匹配三次求和就行了,即每次匹配一个字母 ch
,这样简单易处理,两个字符串这一位都等于 ch
就将他置为 1,否则就置为 0。直接字符串匹配怕是失了智,这波啊,这波是模糊匹配啊,先玩一玩嘛
我们发现每次匹配(这里先匹配 S
):
0123456
RRSPRRSSPSRS0123⬇
0123456
00100011010101234
是 2 和 0 匹配,6 和 4 匹配,好像没什么意思,但是如果我们把 ttt 翻转一下,就会变成 2 和 4 匹配,6 和 0 匹配,2+4=6+0=62+4=6+0 =62+4=6+0=6,欸,这不就是卷积嘛 ?!!
我们知道序列的卷积为:
C(x)=A(x)∗B(x)=∑k=0n+m−2(∑k=i+jaibj)xkC(x)=A(x)* B(x)=\sum_{k=0}^{n+m-2}(\sum_{k=i+j}a_ib_j)x^k C(x)=A(x)∗B(x)=k=0∑n+m−2(k=i+j∑aibj)xk
也就是说我们只需要将 ttt 串翻转,然后直接卷,这样我们每次相当于匹配:s0,tm−1,s1,tm−2⋯s_0,t_m-1,s_1,t_{m-2}\cdotss0,tm−1,s1,tm−2⋯,答案就是 x0+m−1=xm−1x^{0+m-1}=x^{m-1}x0+m−1=xm−1 的系数,以此类推,实际的含义就是 s0s_0s0 与 tm−1t_{m-1}tm−1 匹配,其中 tm−1t_{m-1}tm−1就是翻转后的 t0t_0t0,也就是实际上还是按照规则 s0s_0s0 与 t0t_0t0 匹配,s1s_1s1 与 t1t_1t1 匹配,翻转后只是序号变了,并不影响实际的匹配情况和最后的匹配答案,如果匹配成功,即 1×1=11\times 1=11×1=1,也就是贡献给 xmx^mxm 的系数+1,也就是匹配段为 0∼m−10\sim m-10∼m−1 的答案+1 匹配失败显然就是 1×0=0or 0×0=01\times 0=0 \ \text{or}\ 0\times 0=01×0=0 or 0×0=0。最后最优的答案显然就是三次卷积得到的答案序列:i→m−1∼n+m−2i\to m-1\sim n+m-2i→m−1∼n+m−2 中三个序列相应位置 iii 的权值之和,取最值即可。
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 7, mod = 1e9 + 7;
const double PI = acos(-1.0);
int n, m;
int L, limit = 1;
int RR[N], ans[N];struct Complex
{double x, y;Complex(double x = 0, double y = 0) : x(x), y(y) { }
}sr[N], sp[N], ss[N], tr[N], tp[N], ts[N], ansr[N], ansp[N], anss[N];Complex operator * (Complex J, Complex Q)
{return Complex(J.x * Q.x - J.y * Q.y, J.x * Q.y + J.y * Q.x);}
Complex operator - (Complex J, Complex Q)
{return Complex(J.x - Q.x, J.y - Q.y);}
Complex operator + (Complex J, Complex Q)
{return Complex(J.x + Q.x, J.y + Q.y);}void FFT(Complex * A, int type)
{for(int i = 0; i < limit; ++ i) {if(i < RR[i])swap(A[i], A[RR[i]]);}for(int mid = 1; mid < limit; mid <<= 1) {Complex wn(cos(PI / mid), type * sin(PI / mid));for(int len = mid << 1, pos = 0; pos < limit; pos += len) {Complex w(1, 0);for(int k = 0; k < mid; ++ k, w = w * wn) {Complex x = A[pos + k];Complex y = w * A[pos + mid + k];A[pos + k] = x + y;A[pos + mid + k] = x - y;}}}if(type == -1) {for(int i = 0; i < limit; ++ i) {A[i].x /= limit;}}
}string s, t;int main()
{scanf("%d%d", &n, &m);cin >> s >> t;for(int i = 0; i < n; ++ i) {if(s[i] == 'R') s[i] = 'P';else if(s[i] == 'P') s[i] = 'S';else if(s[i] == 'S') s[i] = 'R';}reverse(t.begin(), t.end());limit = 1, L = 0;while(limit <= n + m) L ++ , limit <<= 1;for(int i = 0; i < limit; ++ i) {RR[i] = (RR[i >> 1] >> 1) | ((i & 1) << (L - 1));}for(int i = 0; i < n; ++ i)if(s[i] == 'R') sr[i].x = 1.0;else sr[i].x = 0.0;for(int i = 0; i < m; ++ i)if(t[i] == 'R') tr[i].x = 1.0;else tr[i].x = 0.0;FFT(sr, 1);FFT(tr, 1);for(int i = 0; i <= limit; ++ i) {ansr[i] = sr[i] * tr[i];}FFT(ansr, -1);for(int i = 0; i < n; ++ i)if(s[i] == 'P') sp[i].x = 1.0;else sp[i].x = 0.0;for(int i = 0; i < m; ++ i)if(t[i] == 'P') tp[i].x = 1.0;else tp[i].x = 0.0;FFT(sp, 1);FFT(tp, 1);for(int i = 0; i <= limit; ++ i) {ansp[i] = sp[i] * tp[i];}FFT(ansp, -1);for(int i = 0; i < n; ++ i)if(s[i] == 'S') ss[i].x = 1.0;else ss[i].x = 0.0;for(int i = 0; i < m; ++ i)if(t[i] == 'S') ts[i].x = 1.0;else ts[i].x = 0.0;FFT(ss, 1);FFT(ts, 1);for(int i = 0; i <= limit; ++ i) {anss[i] = ss[i] * ts[i];}FFT(anss, -1);int maxx = -1;for(int i = m - 1; i < n + m - 1; ++ i) {maxx = max(maxx, (int)(ansr[i].x + 0.5) + (int)(ansp[i].x + 0.5) + (int)(anss[i].x + 0.5));}printf("%d\n", maxx);return 0;
}
百度一搜发现原来FFT本来就可以求字符串匹配呀,那没事了,是我的问题,我太菜了,写的FFT题太少了…
2021年度训练联盟热身训练赛第四场 H - Rock Paper Scissors(字符串匹配,FFT)相关推荐
- 2021年度训练联盟热身训练赛第五场
2021年度训练联盟热身训练赛第五场 链接:https://ac.nowcoder.com/acm/contest/13926 A Binary Seating #include<bits/st ...
- 2021年度训练联盟热身训练赛第八场
目录 2021年度训练联盟热身训练赛第八场 A-Fire on Field 题意 思路 代码 B-Gene Tree 题意 思路 代码 I-Thread Knots 题意 思路 代码 J-Triang ...
- 2021年度训练联盟热身训练赛第三场赛后补题
2021年度训练联盟热身训练赛第三场赛后补题 A Circuit Math [题目分析] [代码展示] B Diagonal Cut [题目分析] [代码展示] C Gerrymandering [题 ...
- 2021年度训练联盟热身训练赛第三场(待补)
文章目录 前言 一.Circuit Math(后缀表达式---栈&&fgets) 二.Diagonal Cut(gcd最大公因数,数论) 三.expected primary-expr ...
- 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)...
2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...
- 2021年度训练联盟热身训练赛第二场(全)
传送门 怎么说呢,这次的训练赛的题目难度不是很大,但就是字多 A Binarize It Professor Boolando can only think in binary, or more sp ...
- 【2021年度训练联盟热身训练赛第五场】Jam-packed
import math as ma if __name__=="__main__":n,m = map(int,input().split())if n < m:
- 【2021年度训练联盟热身训练赛第四场】Game Map(python C++)
#include <bits/stdc++.h> #include <vector> #define ll long long using namespace std; int ...
- 【2021年度训练联盟热身训练赛第四场】Happy Number(python)
import math import cmath import sys import string import heapq import bisect import copy from queue ...
最新文章
- 使用python写Wave文件
- TypeError: Can not convert a float32 into a Tensor or Operation.
- Android SDK tools,platform-tools,build-tools 区别
- 十八、PHP框架Laravel学习笔记——模型的增删改
- ContOS网络连接及简单的ssh Xshell连接!
- ubuntu 开启php mysql扩展_linux(ubuntu/centos)、windows安装php-zip扩展
- 西班牙人:武磊身体无恙 可以出场比赛
- Houdini特效资源如何导入?Houdini工程文件导入教程
- 000 初步使用Kotlin开发Android应用
- 题目1555:重复子串
- python制作简单动画_如何使用python制作简单的动画?
- 全面解读数据中台、数据仓库和数据湖
- zabbix邮箱告警配置
- 解决api打开显示“已取消到该网页的导航”问题或者api里面没有内容
- 省市县三级联动封装邮编数据列表
- 华硕美版路由器RT-AC1200G+解决无线信号弱问题
- 线索树找*p的中序后继且中序遍历 二叉线索树
- php制作万年历的步骤_PHP制作万年历
- Java——LocalDateTime
- 从稻农成长为技术领导者