【折半搜索】AtCoder Grand Contest 026 String Coloring

题意:

给出一个字符串s。
给这个串的每个位置染上红/蓝色,要求正向读每个染成红色的字符所组成的字符串s1,与反向读每个染成蓝色的字符所组成的字符串s2,满足s1=s2


分析:

由于N很小,我们可以考虑折半搜索。先搜前一半,用字符串hash把蓝、红两种颜色的字符串表示出来,存入一个map里面,再搜后一半,还是用字符串hash求出方案数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 350
using namespace std;
typedef unsigned long long ll;
int n;
char s[MAXN];
map<pair<ll,ll> ,ll> used[MAXN][MAXN];
ll ans;
void dfs1(int x,ll sum1,ll sum2,int len1,int len2){
    if(x==n){
        used[len1][len2][make_pair(sum1,sum2)]++;
        return ;
    }
    dfs1(x+1,sum1*131+(ll)(s[x]-'a'+1),sum2,len1+1,len2);
    dfs1(x+1,sum1,sum2*131+(ll)(s[x]-'a'+1),len1,len2+1);
}
void dfs2(int x,ll sum1,ll sum2,int len1,int len2){
    if(x==n-1){
        ans+=used[len1][len2][make_pair(sum1,sum2)];
        return ;
    }
    dfs2(x-1,sum1*131+(ll)(s[x]-'a'+1),sum2,len1+1,len2);
    dfs2(x-1,sum1,sum2*131+(ll)(s[x]-'a'+1),len1,len2+1);
}
int main(){
    SF("%d",&n); 
    SF("%s",s);
    dfs1(0,0,0,0,0); 
    dfs2(2*n-1,0,0,0,0);
    PF("%llu",ans);
} 

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/81055708