题目:简单说就是字符串中如果出现AB这样连着的字符,就要变成BA,而且此题要把字符串看成一个环形的来看
思路:使用动态规划解决,dp[i][0],表示第i个节点没发生变化,dp[i][1],第j个第i个节点发生了变化。首先分析一下几种情况
①当前节点为B,前面一个为A,即为AB,可以由ABB变化得来,还有就是BA变化不可能变化得到AB,可能会有老哥说存在(AAB->ABA这种情况是后面的B调整得到的,现在只考虑当前节点以及前面的节点,所以不考虑此情况),所以我们认为当前B是不会变化的,即dp[i][1] = 0,而B状态不变化则由前面的A决定,即dp[i][1] = dp[i-1][0] + dp[i-1][1];
②当前节点为A,前面一个为B,即为BA,当前的BA可以是有AB转化而来,也可以是没有变化,如果是没有变化的话,前面的B也没变化,即dp[i][0] = dp[i-1][0];如果变化的话,B也随之变化,主要是由B前面的情况决定,即dp[i][1] = dp[i-2][0] + dp[i-2][1];
③前后都相同,即为AA或者BB,则一定没有变化,即dp[i][1] = 0;没变化的情况主要是有前面的情况决定,即dp[i][0] = dp[i-1][0] +dp[i-1][1];
如果都是A或者B,则直接返回1,否则一定可以找到第一个BA的(因为我们是把一个字符串看成一个环形考虑的),把此BA作为一个整体,设当前的B的位置为pos,那么,将从pos+2到pos-1进行判断,如果碰到BA一定是有AB转化得到的,那么会把除BA的全部都判断出来,而BA需要第二个函数判断,即BABA、BABABA这样的情况
看了几个大佬的代码总结的;
参考一:https://blog.csdn.net/lmhacm/article/details/79723475
参考二:https://blog.csdn.net/survivorone/article/details/54236211
参考三:https://blog.csdn.net/qq_39574690/article/details/75933124
代码:
#include<iostream>
#include<string.h>
#define N 110
using namespace std;
int dp[N][2],len;//len用于环形处理时使用
char s[N];//保存字符串
int judge1(int st,int en){
dp[st][0] = 1;//第一个是不变的,
dp[st][1] = 0;
while(st!=en){
st = (st+1)%len;
if(s[st]-1 == s[(st-1+len)%len]){//当前为B,前面一个为A,AB,可以有ABB得到,BA得不到AB的,看出B不变
dp[st][0] = dp[(st-1+len)%len][1];//B不变的情况由前面A的变化决定
dp[st][1] = 0;//由于当前的B不变,所以为0
}else if(s[st]+1 == s[(st-1+len)%len]){//当前为A,前面一个为B,BA
dp[st][0] = dp[(st-1+len)%len][0];//A不变,那么前面的B也不变
dp[st][1] = dp[(st-2+len)%len][0] + dp[(st-2+len)%len][1];//A变化的话,B也会跟着变化,由B前面决定
if(dp[st][1] == 0){//如果位于开始的位置的话,就直接设置为1
dp[st][1] = 1;
}
}else{//当前与前面的相同
dp[st][0] = dp[(st-1+len)%len][0] + dp[(st-1+len)%len][1];//如果变化的话,就由前面总的决定
dp[st][1] = 0;//如果相同的话,就不会变化,故1为0
}
}
return dp[st][0] + dp[st][1];//由开始的两种情况决定
}
int judge2(int st,int en){
int length = 2;//表示最初的BA两个符号
if(s[st] == 'B'){
if(s[(st+1)%len] =='A'){//为BA此情况
st = (st+2)%len;
length += 2;
}else{//为BB此情况
return 0;
}
}
if(s[en] == 'A'){
if(s[(en-1+len)%len == 'B']){//为AB
en = (en-2+len)%len;
length += 2;
}else{//为AA
return 0;
}
}
if(length >= len) {//判断是否为BABA、BABABA这样的情况,judge把除一开始的BA变化的都计算了.还有加上它变化的
return 1;
}
memset(dp,0,sizeof(dp));//如果不是BABA这些情况,就要在判断一次
dp[st][0] = 1;//第一个是不变的,
dp[st][1] = 0;
while(st!=en){
st = (st+1)%len;
if(s[st]-1 == s[(st-1+len)%len]){//当前为B,前面一个为A,AB,可以有ABB得到,BA得不到AB的,看出B不变
dp[st][0] = dp[(st-1+len)%len][1];//B不变的情况由前面A的变化决定
dp[st][1] = 0;//由于当前的B不变,所以为0
}else if(s[st]+1 == s[(st-1+len)%len]){//当前为A,前面一个为B,BA
dp[st][0] = dp[(st-1+len)%len][0];//A不变,那么前面的B也不变
dp[st][1] = dp[(st-2+len)%len][0] + dp[(st-2+len)%len][1];//A变化的话,B也会跟着变化,由B前面决定
if(dp[st][1] == 0){//如果位于开始的位置的话,就直接设置为1
dp[st][1] = 1;
}
}else{//当前与前面的相同
dp[st][0] = dp[(st-1+len)%len][0] + dp[(st-1+len)%len][1];//如果变化的话,就由前面总的决定
dp[st][1] = 0;//如果相同的话,就不会变化,故1为0
}
}
return dp[st][0] + dp[st][1];//由开始的两种情况决定
}
int main(){
int i;
scanf("%s",s);
len = strlen(s);
memset(dp,0,sizeof(dp));//全部初始化为0
for(i=0;i<len;i++){//找到BA这样的,返回的i是当前B的位置
if(s[i]-1 == s[i+1]){
break;
}
}
int begin = (i+2)%len , end = (i-1+len)%len;//先不考虑BA这两个
cout<< judge1(begin,end) + judge2(begin,end);
return 0;
}