Problem Statement
There is a string s consisting of a and b. Snuke can perform the following two kinds of operation any number of times in any order:
- Choose an occurrence of
aaas a substring, and replace it withb. - Choose an occurrence of
bbas a substring, and replace it witha.
How many strings s can be obtained by this sequence of operations? Find the count modulo 109+7.
Constraints
- 1≤|s|≤105
- s consists of
aandb.
Input
Input is given from Standard Input in the following format:
s
Output
Print the number of strings s that can be obtained, modulo 109+7.
Sample Input 1
Copy
aaaa
Sample Output 1
Copy
6
Six strings can be obtained:
aaaaaabababaabba
Sample Input 2
Copy
aabb
Sample Output 2
Copy
5
Five strings can be obtained:
aabbaaabbbabba
Sample Input 3
Copy
ababababa
Sample Output 3
Copy
1
Snuke cannot perform any operation.
Sample Input 4
Copy
babbabaaba
Sample Output 4
Copy
35
之前难题选讲enfris Dark♂佬就讲过这个套路结果没记住。
发现如果把a看成1,b看成2,那么操作前后串的各个位置的数字和模3是余0的。
然后呢,然后好像就不会了。
既然看结果不好办我们就看向过程。
考虑把每一个过程对应一个不同的可以被凑出的字符串。
这之前我们先想一个问题:一串字符串最后能变成一个字符的条件是什么?
首先,字符串各个位置数字的和的模数一定要和最终字符相等。
但是这样是不够的,考虑ababababab....,这样没有连续相同字符就不可能操作。
现在我们就可以这样考虑了,对于t的每个字符依次在s中划分出|t|段子串,每一个子串化简的结果和t一一对应。
那么我们考虑贪心的划分,也就是从S的开头开始每一次都能划分出来就划。
比如:abbabbaaba -> a|b|b|abb|a|aba-> abbba
这样只需要最后一段是%3余0的就可以合法,然后dp模拟这个贪心特判abababab..,这是题解和DZYO大佬给的做法qwq。
然后我发现了这个做法……至今不懂为什么,代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define For(i, a, b) for(register int i = a; i <= b; ++i)
using namespace std;
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
char s[maxn];
int dp[maxn], sum[maxn], n, flag, trans[3] = {0, -1, -1};
void Add(int & a, const int &b) {
a += b;if(a >= mod) a -= mod;
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1), dp[0] = 1;
For(i, 1, n) sum[i] = (sum[i - 1] + (s[i] - 'a' + 1)) % 3;
For(i, 2, n)
if(s[i] == s[i - 1])
{flag = 1; break;}
if(!flag) return printf("1"), 0;
int from; dp[0] = 1;
For(i, 1, n) {
if(!sum[i] && i < n) dp[i] = 1;
Add(dp[i], dp[i - 1]);
from = trans[(sum[i] + (s[i] == 'a' ? 1 : 2)) % 3];
if(~from) Add(dp[i], dp[from]);
trans[sum[i]] = i;
}
printf("%d", dp[n]);
return 0;
}
rockdu
没有帐号? 立即注册