题目描述
一个字符串str的p型编码a的定义如下:把str表示成b1个c1,b2个c2…bn个cn,然后将b1,c1,b2,c2,…,bn,cn收尾拼接成的字符串中最短的字符串设为a。例如:字符串122344111可被描述为"1个1、2个2、1个3、2个4、3个1",因此我们说122344111的p型编码为1122132431。
类似的道理,00000000000可描述为"11个0",因此它的p型编码为110;100200300可描述为"1个1、2个 0、1个2、2个0、1个3、2个0",因此它的p型编码为112012201320。
很显然,一个串str的p型编码是固定的,但是可能有多个串的p型编码相同。现在bx2k获得了一个字符串str的p型编码a,但他不知道原来的字符串是啥,他现在想知道有多少种字符串的p型编码为a。bx2k是个doubi,他来请教傲娇的你。
输入
第一行包含一个字符串,表示字符串a。
输出
第一行包含一个正整数,为str的数量除以998244353的余数。
样例输入
1415
样例输出
2
题解
我们考虑 d p [ i ] dp[i] dp[i]表示在输入字符串中以i为结尾的字符串前缀所对应的字符串数量。换言之,它表示有多少字符串的p型编码为该输入字符串中位置为(1~i)的子串。由于至少两位才能构成一段新的子串
所以容易想到 d p [ i ] dp[i] dp[i] = ∑ k = 2 i \sum_{k=2}^i ∑k=2i d p [ i − k ] dp[i - k] dp[i−k],用一下前缀和优化, s u m [ i ] sum[i] sum[i]表示 ∑ k = 1 i \sum_{k = 1}^i ∑k=1i d p [ i ] dp[i] dp[i]
所以 d p [ i ] dp[i] dp[i] = s u m [ i − 2 ] sum[i - 2] sum[i−2],然而有些情况没有这么简单。当求到 d p [ i ] dp[i] dp[i]时, a [ i − k + 1 ] a[i - k + 1] a[i−k+1]为0,则 d p [ i ] dp[i] dp[i]不能由 d p [ i − k ] dp[i - k] dp[i−k],因此我们再设 s u m 2 [ i ] sum2[i] sum2[i]表示在i之前因为存在0的干扰不能转移到 d p [ i ] dp[i] dp[i]所有 d p [ j ] dp[j] dp[j]之和。
还有我们发现当a为11111时,我们用上面的方法去做,会得到3,而实际答案为1,因为照我们的做法,
有一种方案为“1个1,11个1”,这种方案是不合理的,需要合并为12个1。因此,我们得解决这个问题。
我们发现当求到 d p [ i ] dp[i] dp[i]时,在i前面与 a [ i ] a[i] a[i]相等的位置j所对应的dp[j]不能转移到 d p [ i ] dp[i] dp[i].
我们用 s u m 3 [ i ] sum3[i] sum3[i]表示在当前位置的两个以前所有与a[i]相等的位置j所对应的 d p [ j ] dp[j] dp[j]之和,
至此, d p [ i ] dp[i] dp[i] = s u m [ i − 2 ] sum[i - 2] sum[i−2] - s u m 2 [ i − 2 ] sum2[i - 2] sum2[i−2] - s u m 3 [ a [ i ] ] sum3[a[i]] sum3[a[i]];
边界情况, d p [ 0 ] dp[0] dp[0] = = = 1, d p [ 1 ] dp[1] dp[1] = 0;
注意点:
1.注意减法后的取模
2.当a的长度为1,或a的第一位为0时需要特判,输出0
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 1000005;
const int P = 998244353;
long long dp[N];
long long sum1[N];
long long sum2[N];
char a[N];
long long sum3[10];
int main(){
int i, len;
scanf("%s", a + 1);
len = strlen(a + 1);
dp[0] = 1;
sum1[0] = 1;
if(a[1] == '0'){
printf("0\n");
return 0;
}
if(len == 1){
printf("0\n");
return 0;
}
dp[1] = 0;
for(i = 2; i <= len; i++){
dp[i] = ((sum1[i - 2] - sum2[i - 2] - sum3[a[i] - '0']) % P + P) % P;
sum1[i - 1] = (sum1[i - 2] + dp[i - 1]) % P;
if(a[i] == '0') sum2[i - 1] = (sum2[i - 2] + dp[i - 1]) % P;
else {
sum3[a[i - 1] - '0'] = (sum3[a[i - 1] - '0'] + dp[i - 1]) % P;
sum2[i - 1] = sum2[i - 2];
}
}
printf("%lld\n", dp[len]);
return 0;
}