Theory:
The idea for solving the problem is: for any fibonacci word F(n) = F(n-1)+F(n-2) = F(n-2)+F(n-3)+F(n-2), so word F(n-2) is both suffix and prefix of word F(n). After observing a little more we can find that F(n-2) will always be the prefix for all the rest of the fibonacci word.Now find the minimum F(n-3) that is longer than the pattern.
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <cstdlib>
#define INF 1000000
#define ll long long
using namespace std;
ll fib[105];
string Fib[105];
vector<int> vb;
int *failureFunc;
void kmpsearch(string p,string s,int min_index)
{
int i=1,len=0;
int length = p.size();
//int failureFunc[length];
failureFunc=(int *)malloc(sizeof(int)*length);
failureFunc[0]=0;
while(i<length)
{
if(p[i]==p[len])
{
len+=1;
failureFunc[i]=len;
i+=1;
}
else
{
if(len!=0)
{
len=failureFunc[len-1];
}
else
{
failureFunc[i]=0;
i+=1;
}
}
}
int I = s.size();
i=0;len=0;
vb.clear();
while(i+len<I)
{
if(i>fib[min_index-1])
break;
if(p[len]==s[i+len])
{
if(len==length-1)
{
vb.push_back(i);
}
else
{
len+=1;
continue;
}
}
if(len)
{
i=i+len-failureFunc[len-1];
len=failureFunc[len-1];
}
else
{
i+=1;
}
}
}
void findAt(int min_indx,string p)
{
kmpsearch(p,Fib[min_indx],min_indx);
}
int main()
{
int n;
int kase=1;
string pat;
// string prev,prev1,tmp;
fib[0]=1;fib[1]=1;
Fib[0]="0";Fib[1]="1";
for(int i=2;i<104;i++)
fib[i]=min(fib[i-1]+fib[i-2],9223372036854775805LL);
int ii;
for(ii=1;ii<3 || Fib[ii-3].size()<100000;ii++)
{
Fib[ii+1]=Fib[ii];
Fib[ii+1].append(Fib[ii-1]);
}
while(scanf("%d",&n)!=EOF)
{
cin>>pat;
if(pat=="0")
{
if(n==1)
cout<<"Case "<<kase++<<": "<<0<<"\n";
else if(n==0)
cout<<"Case "<<kase++<<": "<<1<<"\n";
else
cout<<"Case "<<kase++<<": "<<fib[n-2]<<"\n";
continue;
}
else if(pat=="1")
{
if(n==1)
cout<<"Case "<<kase++<<": "<<1<<"\n";
else if(n==0)
cout<<"Case "<<kase++<<": "<<0<<"\n";
else
cout<<"Case "<<kase++<<": "<<fib[n-1]<<"\n";
continue;
}
else
{
int min_idx=3;
while(fib[min_idx-3]<=pat.size())
min_idx+=1;
if(min_idx>n)
min_idx=n;
findAt(min_idx,pat);
ll prev=0,suf=0;
ll overlap[2]={0,0};
int j,k;
int sz=pat.size();
for(int i=0;i<vb.size();i++)
{
j=vb[i];
k=j+sz-1;
if(j<fib[min_idx-2])
{
if(k<fib[min_idx-2])
{
prev+=1;
}
else
overlap[0]+=1;
}
else if(j<fib[min_idx-1])
{
if(k<fib[min_idx-1])
suf+=1;
else
overlap[1]+=1;
}
}
int f=1;
ll tmp;
for(int i=0;i<=n-min_idx+1;i++)//for(int i=min_idx-1;i<=n;i++)
{
f=1-f;
tmp=prev;//initially f(n-2)
prev=prev+suf+overlap[f];//initially this f(n-1)
suf=tmp;
}
cout<<"Case "<<kase++<<": "<<prev<<"\n";
}
}
return 0;
}