整理的算法模板合集: 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∑​ai​bj​)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)相关推荐

  1. 2021年度训练联盟热身训练赛第五场

    2021年度训练联盟热身训练赛第五场 链接:https://ac.nowcoder.com/acm/contest/13926 A Binary Seating #include<bits/st ...

  2. 2021年度训练联盟热身训练赛第八场

    目录 2021年度训练联盟热身训练赛第八场 A-Fire on Field 题意 思路 代码 B-Gene Tree 题意 思路 代码 I-Thread Knots 题意 思路 代码 J-Triang ...

  3. 2021年度训练联盟热身训练赛第三场赛后补题

    2021年度训练联盟热身训练赛第三场赛后补题 A Circuit Math [题目分析] [代码展示] B Diagonal Cut [题目分析] [代码展示] C Gerrymandering [题 ...

  4. 2021年度训练联盟热身训练赛第三场(待补)

    文章目录 前言 一.Circuit Math(后缀表达式---栈&&fgets) 二.Diagonal Cut(gcd最大公因数,数论) 三.expected primary-expr ...

  5. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)...

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  6. 2021年度训练联盟热身训练赛第二场(全)

    传送门 怎么说呢,这次的训练赛的题目难度不是很大,但就是字多 A Binarize It Professor Boolando can only think in binary, or more sp ...

  7. 【2021年度训练联盟热身训练赛第五场】Jam-packed

    import math as ma if __name__=="__main__":n,m = map(int,input().split())if n < m:

  8. 【2021年度训练联盟热身训练赛第四场】Game Map(python C++)

    #include <bits/stdc++.h> #include <vector> #define ll long long using namespace std; int ...

  9. 【2021年度训练联盟热身训练赛第四场】Happy Number(python)

    import math import cmath import sys import string import heapq import bisect import copy from queue ...

最新文章

  1. 使用python写Wave文件
  2. TypeError: Can not convert a float32 into a Tensor or Operation.
  3. Android SDK tools,platform-tools,build-tools 区别
  4. 十八、PHP框架Laravel学习笔记——模型的增删改
  5. ContOS网络连接及简单的ssh Xshell连接!
  6. ubuntu 开启php mysql扩展_linux(ubuntu/centos)、windows安装php-zip扩展
  7. 西班牙人:武磊身体无恙 可以出场比赛
  8. Houdini特效资源如何导入?Houdini工程文件导入教程
  9. 000 初步使用Kotlin开发Android应用
  10. 题目1555:重复子串
  11. python制作简单动画_如何使用python制作简单的动画?
  12. 全面解读数据中台、数据仓库和数据湖
  13. zabbix邮箱告警配置
  14. 解决api打开显示“已取消到该网页的导航”问题或者api里面没有内容
  15. 省市县三级联动封装邮编数据列表
  16. 华硕美版路由器RT-AC1200G+解决无线信号弱问题
  17. 线索树找*p的中序后继且中序遍历 二叉线索树
  18. php制作万年历的步骤_PHP制作万年历
  19. Java——LocalDateTime
  20. 从稻农成长为技术领导者

热门文章

  1. 基于OpenCV与tensorflow实现实时手势识别
  2. 快速系统从零学习OpenCV 4路线图
  3. 高翔Slambook第七讲代码解读(特征点提取)
  4. 分布式系统的面试题11
  5. Idea不能新建package的解决
  6. ORM版学员管理系统
  7. onCompositionStart与compositionend
  8. 数据库事务的四大特性和隔离级别
  9. LVS Nginx HAProxy 优缺点
  10. MySQL视图的创建、修改与删除