UVA 11127 - Triple-Free Binary Strings

Problem J
Triple-Free Binary Strings 
Input: 
Standard Input

Output: Standard Output

 

A binary string consists of ones and zeros. Given a binary string T, if  there is no binary string S such that SSS (concatenate three copies of S together) is a substring of T, we say T is triple-free.
 
A pattern consists of ones, zeros and asterisks, where an asterisk(*) can be replaced by either one or zero. For example, the pattern 0**1 contains strings 0001, 0011, 0101, 0111, but not 1001 or 0000.
 
Given a pattern P, how many triple-free binary strings does it contain?
 
Input
Each line of the input represents a test case, which contains the length of pattern, n(0<n<31), and the pattern P. There can be maximum 35 test cases. 
 
The input terminates when n=0.
 
Output
For each test case, print the case number and the answer, shown below. 

 

Sample Input                       Output for Sample Input

4 0**1
5 *****
10 **01**01**
0
 
Case 1: 2
Case 2: 16
Case 3: 9
 

Problemsetter: Rujia Liu
Special Thanks: Shahriar Manzoor


hash 暴力搜一下就过了....不多说了

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string.h>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int maxn = 30 + 5;
char S[maxn];
int n;
char A[maxn];
int H[maxn];
vector<int> X[16];
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,x,sizeof(a))

int Hash(int l,int r)
{
    return H[r] - (H[l-1] << (r-l+1));
}

bool Ok(int cur)
{
    if (S[cur] != '*' && A[cur] != S[cur]) return false;
    for(int len = 1; cur - len * 3 >= 0; ++len) {
        int h = Hash(cur-3*len+1,cur);
        if (binary_search(X[len].begin(),X[len].end(),h)) return false;
    }
    return true;
}

int dfs(int cur)
{
    if (cur == n+1) return 1;
    A[cur] = '1';
    H[cur] = (H[cur-1]<<1) + 1;
    int sum = 0;
    if (Ok(cur)) {
        sum += dfs(cur+1);
    }
    A[cur] = '0';
    H[cur] = H[cur-1] << 1;
    if (Ok(cur)) {
        sum += dfs(cur+1);
    }
    return sum;
}

void solve()
{
    clr(H,0);
    int ans = dfs(1);
    printf("%d\n",ans);
}

int main()
{
    rep(i,1,11) {
        rep(j,0,1<<i) {
            int x = j + (j << i) + (j << (2*i));
            X[i].push_back(x);
        }
        sort(X[i].begin(),X[i].end());
    }
    int cas = 0;
    while (scanf("%d",&n),n) {
        scanf("%s",S+1);
        ++cas;
        printf("Case %d: ",cas);
        solve();
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值