题意:
给出一个最多150字符长的仅仅有a或b或c组成的字符串
对于每一个操作能够把前面一个字符变成后面一个字符或者把后面的一个字符变成前面一个字符
即能够运行赋值语句 str[i+1] = str[i]; 或者 str[i] = str[i+1];
假设原字符串在运行若干次操作后变成一个a,b,c的字符数量相互不超过1的 字符串, 那么称得到的串为一个合法串
问合法串有多少个。
思路来源于:点击打开链接(推荐,写的好清晰)
思路:
依据性质。不可能交叉替换,如果输入的字符串是 A, 字符串 A'是 A串的同样字符压缩成一个后的结果 ,所以B是由A'一个字符扩展一个区间来的,状态 dp[i][na][nb][nc] 表示 以 A'中第i个字符为结尾的字符a数量为na, 字符b数量为nb, 字符c数量为nc的字符串的数量,防止一个B计算两次,规定下一个字符转移仅仅能用近期的来转移。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 500005 #define MAXN 100005 #define mod 51123987 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-12 typedef long long ll; using namespace std; int n,m,ans,cnt,tot,flag; int dp[155][55][55][55]; int next[155][3]; char s[200],s1[200]; int main() { int i,j,k,t; while(~scanf("%d",&n)) { scanf("%s",s+1); tot=1; s1[1]=s[1]; for(i=2; i<=n; i++) { if(s[i]!=s1[tot]) s1[++tot]=s[i]; } memset(next,0,sizeof(next)); for(j=1; j<=tot; j++) { if(s1[j]=='a') { if(next[0][0]==0) next[0][0]=j; } else if(s1[j]=='b') { if(next[0][1]==0) next[0][1]=j; } else { if(next[0][2]==0) next[0][2]=j; } } for(i=1; i<=tot; i++) { for(j=i; j<=tot; j++) { if(s1[j]=='a') { if(next[i][0]==0) next[i][0]=j; } else if(s1[j]=='b') { if(next[i][1]==0) next[i][1]=j; } else { if(next[i][2]==0) next[i][2]=j; } } } int na,nb,nc; m=n/3+1; dp[0][0][0][0]=1; for(i=0; i<=tot; i++) { for(na=0; na<=m; na++) { for(nb=0; nb<=m; nb++) { for(nc=0; nc<=m; nc++) { if(next[i][0]) { dp[next[i][0]][na+1][nb][nc]+=dp[i][na][nb][nc]; dp[next[i][0]][na+1][nb][nc]%=mod; } if(next[i][1]) { dp[next[i][1]][na][nb+1][nc]+=dp[i][na][nb][nc]; dp[next[i][1]][na][nb+1][nc]%=mod; } if(next[i][2]) { dp[next[i][2]][na][nb][nc+1]+=dp[i][na][nb][nc]; dp[next[i][2]][na][nb][nc+1]%=mod; } } } } } ans=0; if(n%3==0) { for(i=1; i<=tot; i++) { ans+=dp[i][n/3][n/3][n/3]; ans%=mod; } } else if(n%3==1) { for(i=1; i<=tot; i++) { ans+=dp[i][n/3+1][n/3][n/3]; ans+=dp[i][n/3][n/3+1][n/3]; ans+=dp[i][n/3][n/3][n/3+1]; ans%=mod; } } else { for(i=1; i<=tot; i++) { ans+=dp[i][n/3+1][n/3+1][n/3]; ans+=dp[i][n/3+1][n/3][n/3+1]; ans+=dp[i][n/3][n/3+1][n/3+1]; ans%=mod; } } printf("%d ",ans); } return 0; } /* 4 abca */