题目:http://codeforces.com/problemset/problem/264/D
题意:R、B、G组成的两个排石头组,松鼠和猫分别从石头的左端到右端,某一个时刻,你可以允许一种颜色的石头的石头通行。问松鼠和猫可以有多少组相对关系?
分析:状态、字符串,计数
Input
RBR
RGG
Output
5
Input
RGBB
BRRBRR
Output
19
Input
RRRRRRRRRR
RRRRRRRR
Output
8
Note
In the first example, there are five reachable states: (1, 1), (2, 2), (2, 3), (3, 2), and (3, 3). For example, the state (3, 3) is reachable because if you perform instructions "RED", "GREEN", and "BLUE" in this order from the initial state, the state will be (3, 3). The following picture shows how the instructions work in this case.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define change(x) (x == 'R' ? 0 : (x == 'G' ? 1 : 2))
#define LL long long
using namespace std;
void tension(int &a, int &b)
{
if (b < a)
a = b;
}
const int MAXN =(int) 1e6 + 3;
int n, m;
char s[MAXN], t[MAXN];
int p1[MAXN], p2[MAXN];
int sum[MAXN][3][3];
void doing(char* const s, int n, char* const t, int m, int* const num)
{
for (int i = 1; i <= n; i ++)
{
num[i] = num[i - 1] + 1;
while (num[i] < m && t[num[i]] != s[i])
num[i] ++;
tension(num[i], m);
}
}
int main()
{
//printf("Hello world!\n");
scanf("%s\n%s", s + 1, t + 1);
n = strlen(s + 1);
m = strlen(t + 1);
doing(s, n, t, m, p1);
doing(t, m, s, n, p2);
for (int i = 2; i <= m; i ++)
{
for (int j = 0; j < 3; j ++)
for (int k = 0; k < 3; k ++)
{
if (change(t[i - 1]) == j && change(t[i]) == k)
sum[i][j][k] = sum[i - 1][j][k] + 1;
else
sum[i][j][k] = sum[i - 1][j][k];
}
}
LL ans = 0;
int L = 1;
for (int i = 1; i <= n; i ++)
{
int R = p1[i];
while (L <= m && p2[L] < i) L ++;
ans += max(R - L + 1, 0);
// printf("(%d,%d\n",i,L);
if (L <= R && i > 1)
{
int j = change(s[i - 1]);
int k = change(s[i]);
if (j != k)
{
ans -= sum[R][k][j];
ans += sum[L - 1][k][j];
}
}
}
cout << ans << endl;
return 0;
}