神秘代码FZ(暴力模拟/区间dp)


问题 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;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值