问题 D: 神秘代码FZ
问题 D: 神秘代码FZ
时间限制: 1 Sec 内存限制: 128 MB
提交: 42 解决: 13
[提交] [状态] [命题人:admin]
题目描述
Farmer John有一段长度至少为2的仅由大写字母组成的代码,现在他要对这段代码进行一次或一次以上的骚操作。对于一段代码S,Farmer John可以有如下的骚操作:把S的开头一个字母或结尾一个字母去掉,接在S的开头或结尾作为新的代码。例如ABCD经过一次骚操作可以变成的代码有:BCDABCD、ABCDBCD、ABCABCD、ABCDABC。
再举一个例子,ABA经过一次骚操作可以变成的代码有:BAABA、ABABA、ABABA、ABAAB。
尽管ABABA和ABABA看起来是相同的,但由于它是由不同的方式拼接而来,我们认为这两种是不同的方案。
现在给出Farmer John进行了一次或一次以上骚操作的代码,你需要计算可能的操作出这段代码的方案数。
输入
输入只有一行,一个仅由大写字母构成的字符串S,表示操作之后的代码。
输出
输出只有一行,表示可能的方案数。
样例输入
复制样例数据
ABABA
样例输出
6
提示
(1)ABA→AB+ABA。
(2)ABA→ABA+BA。
(3)AB→AB+A→AB+ABA。
(4)AB→AB+A→ABA+BA。
(5)BA→A+BA→AB+ABA。
(6)BA→A+BA→ABA+BA。
对于50%的数据,1≤∣S∣≤300。
对于100%的数据,1≤∣S∣≤105。
思路没啥好说的
注意:位运算加括号
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
char s[N];
int len;
ll dfs(int l,int r){
int t=r-l+1;
if(t<2) return 0;
if((t&1)==0) return 1;
int m=(l+r)>>1;
ll ans=1;
ll L=0,R=0;
bool flag=true;
for(int i=l,j=m;i<m;){//AB ABA(AB是前缀)
if(s[i]==s[j]){
i++;
j++;
}
else{
flag=false;
break;
}
}
if(flag) R++;//ans+=dfs(m,r);
flag=true;
for(int i=m,j=r;j>m;){//ABA BA(BA是后缀)
if(s[i]==s[j]){
i--;
j--;
}
else{
flag=false;
break;
}
}
if(flag) L++;//ans+=dfs(l,m);
flag=true;
for(int i=l,j=m+1;j<=r;){//ABA BA(BA是前缀) 或 AB ABA(AB是后缀) ,两者判断一样
if(s[i]==s[j]){
i++;
j++;
}
else{
flag=false;
break;
}
}
if(flag) L++,R++;//ans+=dfs(l,m)+dfs(m,r);
if(L) ans+=L*dfs(l,m);
if(R) ans+=R*dfs(m,r);
return ans;
}
int main(){
scanf("%s",s+1);
len=strlen(s+1);
printf("%lld\n",dfs(1,len)-1);
return 0;
}