考慮$s$能變成$t$的必要條件(假設$s\ne t$):c++
1.$s$中存在一對相鄰字符不一樣ide
2.$|s|=|t|$且若將a-c對應爲0-2,則字符模3同餘;spa
3.$t$中存在一對相鄰兩個字符相同字符串
同時,對於$|s|\ge 4$,這個充分條件也是必要條件,證實以下:it
概括,對於$|s|=4$暴力驗證,不然考慮經過若干次操做將$s$首或尾的字符與$t$相同,而後刪去這個字符class
具體的構造:若初始相同,直接刪去便可,不然強制$s_{2}=s_{3}=除去s_{1}和t_{1}的另外一種字符$,而後經過$s_{4}$調整模數相等,再令$s_{5}=...=s_{|s|}=a$便可,先將$s[2,|s|]$變爲該字符串,而後再操做一次即相同im
同時爲了保證第2個性質,若僅在首部出現相鄰的相同字符,選擇刪去尾部,且因爲$|s|\ge 4$,首尾相同的部分必然不會重複,所以合法img
對於第一個條件直接斷定(注意還有$s=t$的1種)便可,不然令$f[i][j][k][p]$表示$t$中前$i$個字符和模3爲$j$,最後一個字符爲$k$,是否出現過相鄰字符相同的方案數,轉移分類討論便可di
特別的,若是$s$中沒有相鄰兩個字符,但$t=s$仍然是合法解,答案要加1view
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define mod 998244353 5 int n,sum,ans,vis[3][3][3],f[N][3][3][2]; 6 char s[N]; 7 void dfs(int a,int b,int c){ 8 if (vis[a][b][c])return; 9 vis[a][b][c]=1; 10 ans++; 11 if (a!=b)dfs(3-a-b,3-a-b,c); 12 if (b!=c)dfs(a,3-b-c,3-b-c); 13 } 14 int main(){ 15 scanf("%s",s); 16 n=strlen(s); 17 if (n==2){ 18 printf("%d",1+(s[0]!=s[1])); 19 return 0; 20 } 21 if (n==3){ 22 dfs(s[0]-'a',s[1]-'a',s[2]-'a'); 23 printf("%d",ans); 24 return 0; 25 } 26 bool flag=0; 27 for(int i=1;i<n;i++) 28 if (s[i]!=s[0]){ 29 flag=1; 30 break; 31 } 32 if (!flag){ 33 printf("1"); 34 return 0; 35 } 36 for(int i=0;i<3;i++)f[0][i][i][0]=1; 37 for(int i=1;i<n;i++) 38 for(int j=0;j<3;j++) 39 for(int k=0;k<3;k++) 40 for(int l=0;l<3;l++) 41 for(int p=0;p<2;p++) 42 f[i][j][k][(p|(l==k))]=(f[i][j][k][(p|(l==k))]+f[i-1][(j+3-k)%3][l][p])%mod; 43 sum=0,ans=1; 44 for(int i=0;i<n;i++)sum=(sum+s[i]-'a')%3; 45 for(int i=1;i<n;i++)ans&=(s[i]!=s[i-1]); 46 for(int i=0;i<3;i++)ans=(ans+f[n-1][sum][i][1])%mod; 47 printf("%d",ans); 48 }