[atARC131F]ARC Stamp

为了方便,以下默认字符集为$\{A,R,C\}$

将操作逆向,即将形如ARC的子串变为任意字符,求$T$在$k$步内能得到的$S$数量

考虑给定$S$,如何判定$S$能否被$T$在$k$步内得到——

将任意字符用?表示,称两个字符串匹配即将?替换后两者相同,那么操作即将能与ARC匹配的子串变为???,并判定$k$步内能否得到与$S$匹配的字符串

(注意到当?为了之后的操作而确定后,该次操作后其又会任意)

 

考虑"能与ARC匹配的字符串",显然共有8种,且其中A?C不会出现、???无意义

换言之,?的拓展形式即以下三种:

1.将ARC变为???

2.将一段?左侧的AR/A、右侧的RC/C替换为??/?

3.将两段?之间的R替换为?

重复此过程直至无法拓展,并将每一次拓展的用()表示、无法拓展的部分用(X)代替

考虑其最终的形式,总是形如(X/空)P(R/X/空)P(X/空)(其中P=(AR/A)(ARC)(RC/C),加粗的部分可以重复),且不难证明这样的划分方式是唯一的

考虑对$T$以此法划分,并用$f_{i,j,0/1/2}$表示前$i$个部分中选$j$个、最后一个是否选择以及是否是独立的ARC(注意并不指倒数第2个不选,形如ARCARC后者也是独立的)对应的$S$方案数

关于转移参考代码(即选择合理且某些部分要求严格不同),时间复杂度为$o(|T|^{2})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 5005
 4 #define mod 998244353
 5 #define ll long long
 6 vector<pair<int,int> >v;
 7 int n,m,ans,inv[N],a[N],cnt[N],vis[N],f[N][N][3],len[6]={3,2,1,2,1,1};
 8 char s[N],t[6][3]={{'A','R','C'},{'A','R','?'},{'A','?','?'},{'?','R','C'},{'?','?','C'},{'?','R','?'}};
 9 int main(){
10     inv[0]=inv[1]=1;
11     for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
12     scanf("%s%d",s+1,&m),n=strlen(s+1);
13     while (1){
14         bool Flag=0;
15         for(int i=1;i<=n-2;i++){
16             for(int j=0;j<6;j++){
17                 bool flag=0;
18                 for(int k=0;k<3;k++)
19                     if (s[i+k]!=t[j][k])flag=1;
20                 if (!flag){
21                     Flag=1;
22                     int p=i+2;
23                     if (s[p]=='?')p--;
24                     if (s[p]=='?')p--;
25                     v.push_back(make_pair(p,j));
26                     for(int k=0;k<3;k++)s[i+k]='?';
27                     break;
28                 }
29             }
30             if (Flag)break;
31         }
32         if (!Flag)break;
33     }
34     sort(v.begin(),v.end());
35     n=v.size();
36     for(int i=1;i<=n;i++){
37         a[i]=v[i-1].second;
38         cnt[i]=1;
39         for(int j=0;j<len[a[i]];j++)cnt[i]*=3;
40     }
41     f[0][0][0]=1;
42     for(int i=1;i<=n;i++){
43         for(int j=0;j<=i;j++)f[i][j][0]=f[i-1][j][0];
44         if ((i==1)||(a[i-1]==0)||(a[i-1]==3)||(a[i-1]==4)){
45             for(int j=0;j<=i;j++)
46                 for(int p=1;p<3;p++)f[i][j][0]=(f[i][j][0]+f[i-1][j][p])%mod;
47         }
48         if (!a[i]){
49             if ((a[i-1]!=1)&&(a[i-1]!=2)&&(a[i-1]!=5)){
50                 for(int j=1;j<=i;j++)
51                     for(int p=0;p<3;p++)f[i][j][2]=(f[i][j][2]+(ll)(cnt[i]-1)*f[i-1][j-1][p])%mod;
52             }
53             else{
54                 for(int j=1;j<=i;j++){
55                     f[i][j][1]=(ll)cnt[i]*(f[i-1][j-1][1]+f[i-1][j-1][2])%mod;
56                     f[i][j][2]=(ll)(cnt[i]-1)*f[i-1][j-1][0]%mod;
57                 }
58             }
59             continue;
60         }
61         if ((a[i]==1)||(a[i]==2)){
62             if ((a[i-1]!=1)&&(a[i-1]!=2)&&(a[i-1]!=5)){
63                 for(int j=1;j<=i;j++)
64                     for(int p=0;p<3;p++)f[i][j][1]=(f[i][j][1]+(ll)(cnt[i]-1)*f[i-1][j-1][p])%mod;
65             }
66             else{
67                 for(int j=1;j<=i;j++)f[i][j][1]=(ll)(cnt[i]-1)*f[i-1][j-1][0]%mod;
68                 for(int j=1;j<=i;j++)f[i][j][1]=(f[i][j][1]+(ll)cnt[i]*(f[i-1][j-1][1]+f[i-1][j-1][2]))%mod;
69             }
70         }
71         else{
72             if (a[i-1]){
73                 int s=(ll)(cnt[i]-1)*(inv[cnt[i-1]-1]+1)%mod;
74                 for(int j=1;j<=i;j++)f[i][j][1]=(ll)s*(f[i-1][j-1][1]+f[i-1][j-1][2])%mod;
75             }
76             else{
77                 int s=cnt[i]-1;
78                 for(int j=1;j<=i;j++)f[i][j][1]=(ll)s*f[i-1][j-1][1]%mod;
79                 s=(ll)s*(inv[cnt[i-1]-1]+1)%mod;
80                 for(int j=1;j<=i;j++)f[i][j][1]=(f[i][j][1]+(ll)s*f[i-1][j-1][2])%mod;
81             }
82         }
83     }
84     for(int i=0;i<=m;i++)
85         for(int j=0;j<3;j++)ans=(ans+f[n][i][j])%mod;
86     printf("%d\n",ans);
87     return 0;
88 }
View Code

 

posted @ 2021-12-09 15:15  PYWBKTDA  阅读(155)  评论(0编辑  收藏  举报