Codeforces Gym 101667H (UVA Live 8095) Rock Paper Scissors (FFT) -2017 Daejeon Regional

题目传送门

Problem H

Rock Paper Scissors

Time Limit: 1 Second

There is a Rock Paper Scissors (RPS) machine which generates Rock, Paper, or Scissors randomly. You also have a similar small Rock Paper Scissors machine. Before the game, the RPS machine will generate a list of its choice of Rock, Paper, or Scissors of the length ݊ and your machine also will generates a list of its choice of the length ݉. That is, you know the whole list of the RPS’s choices and you have the list of your machine’s choices. Of course, each choice of the machines is one of the three options (Rock, Paper, or Scissors).

Now, you start playing Rock Paper Scissors game. In every match, you compare the list of RPS’s choice and the list of your machine’s in sequence and decide whose machine would win. However, only you may skip some RPS’s choices to find the position to get the most winning points of your machine. After you decide to start match you cannot skip the match till the end of the match. ‘R’ stands for Rock, ‘P’ stands for Paper, and‘S’ stands for Scissors.

For example, suppose that the RPS’s list is “RSPPSSSRRPPR” and your machine’s list is “RRRR”. To get the most winning points, you should start the match after skipping three RPS’s choices or four RPS’s choices.(See Figure H.1.) Then, you can win in three matches. The draw case is not considered.

Given the list of RPS’s choices and the list of your choices, find the position to get the maximum number of wining matches.

Input

Your program is to read from standard input. The first line contains two positive integers ݊ and ሺ1 ൑ ݉ ൏݊ ൑ 100,000ሻ, where ݊ is the length of the string for RPS machine and ݉ is the length of the string for your machine. 

Following the first line contains the list of choices of RPS machine and the second line contains thelist of choices of your machine.

Output

Your program is to write to standard output. The first line should contain an integer indicating the maximum number of wining matches. The following shows sample input and output for four test cases.



给两个仅由RPS构成的字符串,长短不一,问你把短串从长串某个位置开始一一匹配字符,最多可以匹配多少位。


可以对每一种字符单独计算答案,把字符匹配的过程看做卷积和,则当前要匹配的字符对应1,否则为0,把其中一个串反转,就只要算这两个01数列的卷积和即可。

利用FFT算出每种字符匹配对答案的贡献,最后相加取最大值即可。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn = 400005, inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const ld pi = acos(-1.0L);
char s[maxn], t[maxn];
int n1, n2, m;

struct complex
{
	double r, i;
	complex(double _r = 0, double _i = 0)
	{
		r = _r; i = _i;
	}
	complex operator +(const complex &b)
	{
		return complex(r + b.r, i + b.i);
	}
	complex operator -(const complex &b)
	{
		return complex(r - b.r, i - b.i);
	}
	complex operator *(const complex &b)
	{
		return complex(r*b.r - i * b.i, r*b.i + i * b.r);
	}
};
complex conj(complex a) {
	return complex(a.r, -a.i);
}
complex a[maxn], b[maxn];
int ans[maxn];

struct fff {
	int n, rev[maxn];
	complex o[maxn], oi[maxn];

	void init(int m) {
		n = 1;
		int k = 0;
		mem0(rev); mem0(o); mem0(oi);
		while (n < m) n <<= 1, k++;
		for (int i = 0; i < n; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
		for (k = 0; k < n; k++) {
			o[k] = complex(cos(2 * pi / n * k), sin(2 * pi / n * k));
			oi[k] = conj(o[k]);
		}
	}

	void fft(complex *a, complex *w) {
		for (int i = 0; i < n; i++)
			if (i < rev[i]) swap(a[i], a[rev[i]]);
		for (int l = 2; l <= n; l <<= 1) {
			int m = l >> 1;
			for (complex *p = a; p != a + n; p += l)
				for (int k = 0; k < m; k++) {
					complex t = w[n / l * k] * p[k + m];
					p[k + m] = p[k] - t;
					p[k] = p[k] + t;
				}
		}
	}

	void dft(complex *a, int f) {
		if (f == 1) fft(a, o); else {
			fft(a, oi);
			for (int i = 0; i < n; i++) a[i].r /= n;
		}
	}

	void mul(complex *a, complex *b, int m) {
		init(m);
		dft(a, 1); dft(b, 1);
		for (int i = 0; i < n; i++) a[i] = a[i] * b[i];
		dft(a, -1);
	}
};
fff f;

void cal(char c) {
	mem0(a); mem0(b);
	for (int i = 0; i < n1; i++) if (s[i] == c) a[i].r = 1; else a[i].r = 0;
	for (int i = 0; i < n2; i++) if (t[i] == c) b[i].r = 1; else b[i].r = 0;
	f.mul(a, b, m);
	for (int i = 0; i < m; i++) ans[i] += floor(a[i].r + 0.5);
}

int main() {
	int i, j;
	scanf("%d%d", &n1, &n2);
	scanf("%s", s); scanf("%s", t);
	m = n1 + n2 - 1;
	for (i = 0; i < n1; i++) {
		if (s[i] == 'R') s[i] = 'P'; else
			if (s[i] == 'P') s[i] = 'S'; else s[i] = 'R';
	}
	strrev(t);
	cal('R'); cal('P'); cal('S');
	int ANS = -1;;
	for (i = n2-1; i < m; i++) ANS = max(ANS, ans[i]);
	printf("%d\n", ANS);
//	system("pause");
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值