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