Live2D

[AGC027E] ABBreviate 题解

link

Description

一个长度为 \(n\) 的字符串,每次可以将 aa 变为 b,也可以将 bb 变为 a,问最后能变到的不同字符串个数。

\(n\le 10^5\)

Solution

可以看出的是我们将 a/b 的权值设为 1/2,那么每次操作在 \(\% 3\) 意义下和并不会改变,那么考虑一个字符串 s 能否变为一个字符串 t,可以看出的是我们每次前缀选一段出来消掉,并且我们只需要第一步满足存在两个相邻相同字符,可以保证后面每一步都存在相邻相同字符。我们只需要判断一个字符串能否变为一个字符 c,发现在保证整个字符串 s 存在相邻相同字符之后,只需要判断和是否相等。

不过这样贪心的删可能最后会剩下一段和为 \(0\),可以发现的是这种一定可以并入前面。比如剩下 abab,如果前面是 a,我们可以直接删掉,如果前面是 b,我们可以保留最后的b,让 baba 继续向前面传递。

所以每次我们只需要找到离该点最近的能构成 a/b 的点即可直接 dp 转移。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 500005

char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

char s[MAXN];
int n,f[MAXN],nxt[MAXN][2];

#define mod 1000000007
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}

signed main(){
	scanf ("%s",s + 1),n = strlen (s + 1),f[n + 1] = 1;bool flg = 0;
	for (Int i = 1;i < n;++ i) flg |= (s[i] == s[i + 1]);
	if (!flg) return puts ("1") & 0;
	for (Int d = 0;d < 2;++ d) nxt[n + 1][d] = nxt[n + 2][d] = n + 2;
	int sum = 0;
	for (Int i = n;i >= 1;-- i){
		(sum += (s[i] - 'a' + 1)) %= 3;
		nxt[i][0] = (s[i] == 'a' ? i + 1 : (s[i + 1] == 'b' ? i + 2 : nxt[i + 2][0]));
		nxt[i][1] = (s[i] == 'b' ? i + 1 : (s[i + 1] == 'a' ? i + 2 : nxt[i + 2][1]));
		f[i] = add (add (f[nxt[i][0]],f[nxt[i][1]]),(sum == 0));
	}
	write (dec (f[1],(sum == 0))),putchar ('\n');
	return 0;
}
posted @ 2022-03-27 11:50  Dark_Romance  阅读(43)  评论(0编辑  收藏  举报