#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <cstring>
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <list>  
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;  

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }


const int MAXSTATE=161;
const int MAXBF=21;

bool ok[MAXBF+1][1<<MAXBF]; // ok[i][mask] = whether string of length i given by mask is beautiful

void bf() {
	memset(ok,false,sizeof(ok));
	ok[1][1<<0]=true;
	for(int len=3;len<=MAXBF;len+=2) REP(mask,1<<len) {
		REP(i,len-2) {
			int a=mask&((1<<i)-1);
			int b=(mask>>i)&7;
			int c=mask>>(i+3);
			int v=b==3||b==5||b==6||b==7?1:0;
			int nmask=a|(v<<i)|(c<<(i+1));
			if(ok[len-2][nmask]) ok[len][mask]=true;
		}
	}
	//for(int len=3;len<=7;len+=2) REP(mask,1<<len) if(ok[len][mask]) { REP(i,len) printf("%c",mask&(1<<i)?'x':'.'); puts(""); }
}

const string REPLACE[4][2]={{"000","0"},{"010","0"},{"11011","111"},{"1100110011","110011"}};

int nstate;
map<string,int> mp;
int nxt[MAXSTATE][2];
queue<string> q;
vector<string> states;
int sstate,wstate;
vector<bool> winning;

int ensurestate(string s) {
	if(mp.count(s)) return mp[s];
	int ret=nstate++; mp[s]=ret; REP(i,2) nxt[ret][i]=-2; q.push(s); states.PB(s); winning.PB(false);
	//printf("%d: '%s'\n",ret,s.c_str());
	return ret;
}

bool win(string s) {
	int nthree=0;
	FORSZ(i,2,s) {
		if(s[i]=='1'&&s[i-1]=='1'&&s[i-2]=='1') {
			if(i>=3&&s[i-3]=='1') return true;
			++nthree;
		}
	}
	return nthree>=2;
}

string normalize(string s) {
	REP(i,4) {
		if(SZ(s)<SZ(REPLACE[i][0])) continue;
		if(s.substr(SZ(s)-SZ(REPLACE[i][0]))!=REPLACE[i][0]) continue;
		return normalize(s.substr(0,SZ(s)-SZ(REPLACE[i][0]))+REPLACE[i][1]);
	}
	return s;
}

void gen() {
	nstate=0; mp.clear(); states.clear(); winning.clear();
	wstate=ensurestate("!"); REP(i,2) nxt[wstate][i]=wstate; winning[wstate]=true;
	q=queue<string>(); sstate=ensurestate("");
	while(!q.empty()) {
		string s=q.front(); q.pop();
		int at=mp[s];
		REP(i,2) {
			string t=normalize(s+string(1,'0'+i));
			//if(SZ(s)<=3) printf("%s %d -> %s\n",s.c_str(),i,t.c_str());
			if(win(t)) nxt[at][i]=wstate; else nxt[at][i]=ensurestate(t);
		}
	}
	bf();
	FOR(i,1,nstate) {
		string s=states[i];
		int len=SZ(s),mask=0; REP(j,len) if(s[j]=='1') mask|=1<<j;
		assert(len<=MAXBF);
		winning[i]=ok[len][mask];
	}
	//printf("%d\n",nstate);
	//REP(i,nstate) printf("%d: %d %d (%s) %s\n",i,nxt[i][0],nxt[i][1],states[i].c_str(),winning[i]?"winning":"losing");
}

const int MAXLEN=300000;
const int MOD=1000000007;

char s[MAXLEN+1]; int slen;

int ways[2][MAXSTATE];

void inc(int &a,int b) { if((a+=b)>=MOD) a-=MOD; }
void run() {
	scanf("%s",s); slen=strlen(s);

	int at=0; memset(ways[at],0,sizeof(ways[at])); ways[at][sstate]=1;
	REP(i,slen) {
		int to=1-at;
		memset(ways[to],0,sizeof(ways[to]));
		REP(j,MAXSTATE) if(ways[at][j]!=0) REP(k,2) {
			if(s[i]!='?'&&s[i]!='0'+k) continue;
			int nj=nxt[j][k];
			inc(ways[to][nj],ways[at][j]);
		}
		at=to;
	}
	int ret=0; REP(i,nstate) if(winning[i]) inc(ret,ways[at][i]);
	//REP(i,nstate) if(ways[at][i]>0) printf("%d * %s\n",ways[at][i],states[i].c_str());
	printf("%d\n",ret);
}

int main() {
	gen();
	run();
	//stress();
	return 0;
}


Measured memory_bytes: 45568