测试样例二中,可能的初始排列为:"AABBB"和"BABBA"。
题解:AB->BA
解题思路是dp,通过dp[position][0]与dp[position][1]分别记路position位置不经变化或经变化得到。
转移方程:1.当前与前邻相同时,不可能有反转而得。dp[now][0] = dp[pre][0]+dp[pre][1],dp[now][1] = 0;
2.当前为'B',前邻为'A',不可能由翻转得到(翻转得到的唯一状态为'BA'),但'AB'为不稳定状态,在当前‘B’看来,'A'一定经过翻转(实际不一定,在'B'的后邻会弥补)dp[now][0] = dp[pre][1]; dp[now][1] = 0;
3.当前为'A',前邻为'B',dp[now][0] = dp[pre][0]; dp[now][1] = dp[ppre][0] + dp[ppre][1];
大致思路明了,首要问题是要找一个稳定状态(即确定变化可能情况的位置)来确定start与enda位置。'AA'或'BB'是稳定的,当不具有普遍性,比如'ABABAB'不存在'AA'或'BB'。因此取'BA'位置,当不存在'BA'时,那么它必然是纯A或纯B串,答案就是1。
否则将一次'BA'出现位置找出来,记B位置为pos,start = (pos+2)%len, enda = (pos-1+len)%len。
初始化dp[start][0] = 1, dp[start][1] = 0。sum = dp[enda][0]+dp[enda][1]。这是默认该‘BA’是反转而来的所得结果。这种情况下不必考虑'BA'前邻与后邻的情况,因为反转之前'AB'与前邻和后邻不具有不稳定状态的可能性。
其次,考虑'BA'未经反转,一直如次,这种情况在前邻'AA'或后邻'BB'的情况下是不成立的。因此前邻是'AA'或后邻是'BB'时,上述sum就是最终结果。
当前邻是'B'&&后邻是'A'时,未经反转是可能的,求解与翻转时相同。sum+未翻转时情况为最终解。
当前邻是'BA'或后邻是'BA'时,比如说前邻是'BA',那么由于这段前邻一定不是反转而来的,它失去了dp性,因此将enda后退两格,诸如此。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
char s[101];
int len,start,enda;
ll dp[100][2];
int main()
{
while(scanf("%s",s)!=EOF)
{
len = strlen(s);
bool mark = true;
for(int i = 1; i<len; i++)
{
if(s[i] != s[(i-1+len)%len])
{
mark = false;
break;
}
}
if(mark)
{
printf("1\n");
continue;
}
for(int i = 0; i<len; i++)
{
int pre = (i-1+len)%len;
if(s[i] == 'A' && s[pre] == 'B')
{
start = (i+1)%len;
enda = (pre-1+len)%len;
break;
}
}
memset(dp,0,sizeof(dp));
dp[start][0] = 1;
dp[start][1] = 0;
for(int i = start; ; )
{
if(i%len == enda)
break;
i++;
int now = i%len;
int pre = (i-1)%len;
if(s[now] == s[pre])
{
dp[now][0] = dp[pre][0] + dp[pre][1];
dp[now][1] = 0;
}
else if(s[now] == 'B')
{
dp[now][0] = dp[pre][1];
dp[now][1] = 0;
}
else
{
dp[now][0] = dp[pre][0];
dp[now][1] = dp[(pre-1+len)%len][0] + dp[(pre-1+len)%len][1];
if(dp[now][1] == 0)
dp[now][1] = 1;
}
}
ll sum = dp[enda][0] + dp[enda][1];
if((s[enda] == 'A' && s[(enda-1+len)%len] == 'A') || (s[start] == 'B' && s[(start+1)%len] == 'B'))
{
printf("%I64d\n",sum);
continue;
}
if(s[enda] == 'A' && s[(enda-1+len)%len] == 'B')
enda = (enda-1+len)%len;
if(s[start] == 'B' && s[(start+1)%len] == 'A')
start = (start+2)%len;
if((start-1+len)%len == enda)
{
printf("I64d\n",sum+1);
continue;
}
memset(dp,0,sizeof(dp));
dp[start][0] = 1;
dp[start][1] = 0;
for(int i = start; i!=enda ; )
{
if(i%len == enda)
break;
i++;
int now = i%len;
int pre = (i-1)%len;
if(s[now] == s[pre])
{
dp[now][0] = dp[pre][0] + dp[pre][1];
dp[now][1] = 0;
}
else if(s[now] == 'B')
{
dp[now][0] = dp[pre][1];
dp[now][1] = 0;
}
else
{
dp[now][0] = dp[pre][0];
dp[now][1] = dp[(pre-1+len)%len][0] + dp[(pre-1+len)%len][1];
if(dp[now][1] == 0)
dp[now][1] = 1;
}
}
sum+=(dp[enda][0]+dp[enda][1]);
printf("%I64d\n",sum);
}
return 0;
}