#include<bits/stdc++.h>
#define N (1000010)
#define int long long
#define sort stable_sort
using namespace std;
namespace IO
{
#define ll unsigned long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
long long n,m;
namespace hs
{
int hs[1010],to[100010],nxt[100010];
int mod=98317,head[100010],cnmhs;
void clean(){memset(head,0,sizeof(head));}
void add(int x,int P=mod)
{
hs[++cnmhs]=x,to[cnmhs]=P,x%=mod,
nxt[cnmhs]=head[x],head[x]=cnmhs;
}
int find_x(int x)
{
for(int i(head[x%mod]);i;i=nxt[i])
if(hs[i]==x)return to[i];
return -1;
}
}
namespace math
{
int t,P,q,d;
int x,y,k,ans,possible,lon;
int mod[N],a[N],gt[N],nth_mod[N];
int len,prime[700010],phi[N];//线性筛欧拉函数
short mu[N];
int mtot;
bitset<N>vis;
int jc[N],cp[N];
long long inv[N];//乘法逆元
long long qpow(long long x,int b,int P=P)
{
long long ans=1;
for(;b;b>>=1){if(b&1)ans=(ans*x)%P;x=(x*x)%P;}
return ans;
}//O(log(b))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int exgcd(int a,int b,int &x,int &y)
{
if(!b){x=1,y=0;return a;}
int d=exgcd(b,a%b,y,x);
y-=(a/b*x);
return d;
}//O(max(a,b))
int ola(int n)
{
int ans=n;
for(int i=2;i*i<=n;++i)
{
if(n%i==0)ans=ans/i*(i-1);
for(;n%i==0;n/=i);
}
if(n>1)ans=ans/n*(n-1);
return ans;
}//O(sqrt(n))
void eular(int n)//欧拉筛
{
//memset(vis,0,sizeof(vis));
phi[1]=1;
for(int i(2);i<=n;++i)
{
if(!vis[i])
prime[++len]=i,phi[i]=(i-1);
for(int j(1);j<=len&&i*prime[j]<=n;++j)
{
vis[i*prime[j]]=1;
if(!(i%prime[j]))
{phi[i*prime[j]]=(phi[i]*prime[j]);break;}
else phi[i*prime[j]]=(phi[i]*(prime[j]-1));
}
}
}//O(n)
void mobius(int n)
{
//memset(vis,0,sizeof(vis));
mu[1]=1;
for(int i(2);i<=n;++i)
{
if(!vis[i])prime[++mtot]=i,mu[i]=-1;
for(int j(1);j<=mtot&&i*prime[j]<=n;++j)
{
vis[i*prime[j]]=1;
if(!(i%prime[j])){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=~mu[i]+1;
}
}
}//O(n)
void eular_mobius(int n)
{
//memset(vis,0,sizeof(vis));
mu[1]=phi[1]=1;
for(int i(2);i<=n;++i)
{
if(!vis[i])prime[++len]=i,phi[i]=(i-1),mu[i]=-1;
for(int j(1);j<=len&&i*prime[j]<=n;++j)
{
vis[i*prime[j]]=1;
if(!(i%prime[j]))
{
phi[i*prime[j]]=(phi[i]*prime[j]);
mu[i*prime[j]]=0;
break;
}
phi[i*prime[j]]=(phi[i]*(prime[j]-1));
mu[i*prime[j]]=~mu[i]+1;
}
}
}
void niyuan1(int n,int P=P)//乘法逆元
{
inv[1]=1;
for(int i(2);i<=n;++i)inv[i]=((P-P/i)*inv[P%i])%P;
}//O(n)
int inv_it(int a,int P=P)//O(log(a))
{
int d(exgcd(a,P,x,y));
return(x%P+P)%P;
}
int C(int n,int m,int P=P)
{
if(m>n)return 0;
int a(1),b(1);
for(int i(n-m+1);i<=n;++i)a=(a*i)%P;
for(int i(2);i<=m;++i)b=(b*i)%P;
return(a*qpow(b,P-2,P))%P;
}
int jc_C(int n,int m,int P=P)
{
return ((jc[n])*inv_it(jc[m])%P*inv_it(jc[n-m]))%P;
}
int lucas(int n,int m,int P=P)
{return(!m)?1:(C(n%P,m%P,P)*lucas(n/P,m/P,P))%P;}
int excrt(int n)//扩展中国剩余定理
{
int mul(mod[1]);ans=a[1];
int x,y,c,d;
for(int i(2);i<=n;++i)
{
x=y=0;
c=(a[i]-ans%mod[i]+mod[i])%mod[i];
d=exgcd(mul,mod[i],x,y);
if(!(c%d))
ans+=(((x+mod[i])%mod[i])*(c/d)%mod[i])*mul,
mul=mul*mod[i]/gcd(mul,mod[i]),
ans%=mul;
else return -1;
}
return ans%mul;
}
int exlucas_jc(int n,int mod,int P=P)
{
if(!n)return 1;
int res(1);
for(int i(1);i<=P;++i)//不含因子mod[now]
if(i%mod)res=(res*i)%P;
res=qpow(res,n/P,P);
for(int i(1);i<=n%P;++i)if(i%mod)res=(res*i)%P;
return(res*(exlucas_jc(n/mod,mod,P)))%P;
}
int cal(int n,int m,int mod,int P=P)
{
int c1(exlucas_jc(n,mod,P));
int c2(exlucas_jc(m,mod,P));
int c3(exlucas_jc(n-m,mod,P));
int cnt(0);
for(int i(n);i;i/=mod)cnt+=(i/mod);
for(int i(m);i;i/=mod)cnt-=(i/mod);
for(int i(n-m);i;i/=mod)cnt-=(i/mod);
return(((qpow(mod,cnt,P)*c1)%P*inv_it(c2,P))%P*inv_it(c3,P))%P;
}
inline int crt(int x,int mod,int P)
{
return inv_it(P/mod,mod)*(P/mod)*x;
}
int exlucas(int n,int m,int now,int P)
{return(crt(cal(n,m,nth_mod[now],mod[now]),mod[now],P));}
int bsgs(int x,int y,int P=P)
{
if(!(x%P))return -1;
x%=P,y%=P;
if(y==1)return 0;
int Z(sqrt(P)+1);
int xx(y),yy;
hs::clean();
for(int i(0);i<Z;++i,xx=(xx*x)%P)hs::add(xx,i);
yy=qpow(x,Z),xx=1;
for(int i(1),k;i<=Z;++i)
{
xx=(xx*yy)%P,k=hs::find_x(xx);
if(k!=-1)return i*Z-k;
}
return -1;
}
void error_sort(int n)
{for(int i(2);i<=n;++i)cp[i]=(i*cp[i-1]+((i&1)?-1:1))%P;}
void jc_set(int n)
{jc[0]=jc[1]=1;for(int i(2);i<=n;++i)jc[i]=(jc[i-1]*i)%P;}
}
/*
namespace kill_tree
{
#define ls (p<<1)
#define rs (p<<1|1)
vector<int>e[N];
struct tt
{
int l,r;
long long add,sum,min;
}tr[N<<2];
int rt,r,cnt,head[N],f[N],d[N],root,b[N];
int siz[N],son[N],rk[N],top[N],dfn[N],cnm,a[N];
int pd[N];
void dfs1(int x,int fa)
{
d[x]=d[fa]+1;
f[x]=fa;
siz[x]=1;
for(int y:e[x])
{
if(y==fa)continue;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]])son[x]=y;
}
}
void dfs2(int x,int t)
{
top[x]=t;
dfn[x]=++cnt;
rk[cnt]=x;
b[cnt]=a[x];
if(!son[x])return;
dfs2(son[x],t);
for(int y:e[x])
if(y!=f[x]&&y!=son[x])
dfs2(y,y);
}
int lca(int x,int y)
{
for(;top[x]!=top[y];x=f[top[x]])
if(d[top[x]]<d[top[y]])swap(x,y);
return d[x]>d[y]?y:x;
}
int find(int x,int y)
{
for(;top[x]!=top[y];x=f[top[x]])
{
if(d[top[x]]<d[top[y]])swap(x,y);
if(d[top[x]]==y)return top[x];
}
return d[x]<d[y]?son[x]:son[y];
}
void pushup(int p)
{
tr[p].sum=tr[ls].sum+tr[rs].sum;
tr[p].min=min(tr[ls].min,tr[rs].min);
}
void pushdown(int p)
{
if(tr[p].add)
tr[ls].sum+=tr[p].add*(tr[ls].r-tr[ls].l+1),
tr[rs].sum+=tr[p].add*(tr[rs].r-tr[rs].l+1),
tr[ls].min+=tr[p].add,tr[rs].min+=tr[p].add,
tr[ls].add+=tr[p].add,tr[rs].add+=tr[p].add,
tr[p].add=0;
}
void build(int p,int l,int r)
{
tr[p].l=l,tr[p].r=r;
if(l==r){tr[p].sum=tr[p].min=a[l];return;}
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
pushup(p);
}
void update(int p,int l,int r,long long k)
{
if(l<=tr[p].l&&r>=tr[p].r)
{
tr[p].sum+=k*(tr[p].r-tr[p].l+1);
tr[p].min+=k;tr[p].add+=k;
return;
}
int mid=(tr[p].l+tr[p].r)>>1;
pushdown(p);
if(l<=mid)update(ls,l,r,k);
if(r>mid)update(rs,l,r,k);
pushup(p);
}
void update_path(int p,int v,long long k)
{
for(;top[p]!=top[v];p=f[top[p]])
{
if(d[top[p]]<d[top[v]])swap(p,v);
update(1,dfn[top[p]],dfn[p],k);
}
if(d[p]<d[v])swap(p,v);
update(1,dfn[v],dfn[p],k);//最后一段
}
void upd(int x,int y,long long z)
{
int l=lca(x,y);int r=f[l];
update(1,dfn[x],dfn[x],z),update(1,dfn[y],dfn[y],z),
update(1,dfn[l],dfn[l],~z+1),update(1,dfn[r],dfn[r],~z+1);
}
void update_tree(int p,long long k){update(1,dfn[p],dfn[p]+siz[p]-1,k);}
long long querysum(int p,int l,int r)
{
long long ans=0;
if(l<=tr[p].l&&r>=tr[p].r)return tr[p].sum;
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
while(l<=mid)ans+=querysum(ls,l,r);
if(r>mid)ans+=querysum(rs,l,r);
return ans;
}
long long querysum_path(int p,int v)
{
//p,v为旧点编号
//把树链剖分成若干个重链,重链在序列中编号连续
long long ans=0;
for(;top[p]!=top[v];p=f[top[p]])
{
if(d[top[p]]<d[top[v]])swap(p,v);
ans+=querysum(1,dfn[top[p]],dfn[p]);
}
if(d[p]<d[v])swap(p,v);
ans+=querysum(1,dfn[v],dfn[p]);
return ans;
}
long long querysum_tree(int x)
{
if(x==root)return querysum(1,1,n);
else
if(lca(x,root)!=x)
return querysum(1,dfn[x],dfn[x]+siz[x]-1);
else{int dson=find(x,root);return querysum(1,1,dfn[dson]-1),querysum(1,dfn[dson]+siz[dson],n);}
}
int querymin(int p,int l,int r)
{
int res=0x7f7f7f7f;
if(tr[p].l>=l&&tr[p].r<=r)return tr[p].min;
int mid=tr[p].l+tr[p].r>>1;
while(l<=mid)res=min(res,querymin(ls,l,r));
if(r>mid)res=min(res,querymin(rs,l,r));
return res;
}
#undef ls
#undef rs
}
namespace modui
{
int len,ans;
int a[50010];
int res,l,r,k;
int out[50010],cnt[50010];
struct aa{int l,r,id;}q[50010];
bool cmp(aa a,aa b)
{return (a.r/len==b.r/len)?a.l<b.l:a.r<b.r;}
void add(int x){ans+=(((++cnt[a[x]])<<1)-1);}
void del(int x){ans-=((--cnt[a[x]]<<1)+1);}
//左端点递增,每块内按照右端点排序
}
namespace MST
{
int f[10010],w;
struct aa{int x,y,w;}e[10010];
bool cmp(aa x,aa y){return x.w<y.w;}
int find(int x){if(x==f[x])return x;return f[x]=find(f[x]);}
void unionf(int x,int y){x=find(x),y=find(y);f[x]=y;}
}
*/
namespace image
{
int head[100010],cnt,dis[100010];
struct aa{int nxt,to,w;}e[1000010];
void add(int x,int y,int w)
{e[++cnt]={head[x],y,w};head[x]=cnt;}
/*
void spfa(int x)
{
queue<int>q;
bitset<100010>flag;
memset(dis,0x3f,sizeof(dis));
dis[x]=0,q.push(x),flag[x]=1;
for(;!q.empty();)
{
int k=q.top();
q.pop(),flag[k]=0;
for(int i(head[k]);i;i=e[i].nxt)
{
int y(e[i].to);
if(dis[y]<dis[k]+e[i].to)
dis[y]=dis[k]+e[i].to,
q.push(y),flag[y]=1;
}
}
}
*/
bitset<100010>flag;
bool dfs_spfa(int x)
{
flag[x]=1;
for(int i(head[x]);~i;i=e[i].nxt)
{
int y(e[i].to);
if(dis[y]>dis[x]+e[i].w)
{
dis[y]=dis[x]+e[i].w;
if(flag[x]||!dfs_spfa(x))
return false;
}
}
flag[x]=0;
return true;
}
}
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
namespace KMP
{
/*
void nxt_set(char p[])
{
nxt[0]=-1;
int len(strlen(p));
for(int j(0),k(-1);j<len;)
{
if(k==-1||p[j]==p[k])
{
++k,++j;
if(p[j]==p[k])nxt[j]=nxt[k];
else nxt[j]=k;
}
else k=nxt[k];
}
}
int kmp(char t[],char p[])
{
int lt(strlen(t)),lp(strlen(p));
int i(0),j(0);
nxt_set(p);
for(;i<lt&&j<lp;)
{
if(j==-1||t[i]==p[j])
++i,++j;
else j=nxt[j];
}
if(j==lp)return i-j;
else return -1;
}
*/
int nxt[1000010];
void nxt_set(char b[])
{
for(int i(2),j(0);i<=m;++i)
{
while(j&&b[i]!=b[j+1])j=nxt[j];
if(b[j+1]==b[i])++j;
nxt[i]=j;
}
}
void kmp(char a[],char b[])
{
int j(0);
for(int i(1);i<=n;++i)
{
while(j&&a[i]!=b[j+1])j=nxt[j];
if(b[j+1]==a[i])++j;
if(j==m)write(i-m+1,'\n'),j=nxt[j];
}
}
}
using namespace KMP;
long long x,y,w,t;
char c[1000010],d[1000010];
signed main()
{
init_set();
cin>>c+1>>d+1;
n=(strlen(c+1)),m=(strlen(d+1));
nxt_set(d);
kmp(c,d);
for(int i(1);i<=m;++i)write(nxt[i],' ');
flush();
return 0;
}