【泛刷题】TJOI2017(BZOJ4887~4892)

【前言】
刚刚从雅礼集训回来,老师免了期末考。
同时看着一批dalao去WC签约,而我只能在这里恢复训练。

【题目】
BZOJ
luogu

BZOJ4887 可乐

f i , j f_{i,j} fi,j表示第 i i i秒在第 j j j个城市的方案数,写出转移方程用矩乘优化即可。
当然还要记录一个计数器。
复杂度 O ( n 3 log ⁡ t ) O(n^3\log t) O(n3logt)

#include<bits/stdc++.h>
using namespace std;

const int N=33,mod=2017;
int n,m,T;

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

struct Matrix
{
	int a[N][N];
	void clear(){memset(a,0,sizeof(a));}
	void one(){clear();for(int i=1;i<=n+1;++i)a[i][i]=1;}
	//void print(){for(int i=1;i<=n+1;++i,puts(""))for(int j=1;j<=n+1;++j)printf("%d ",a[i][j]);puts("");}
}tran,ans;
Matrix operator *(const Matrix&x,const Matrix&y)
{
	Matrix res;res.clear();
	for(int i=1;i<=n+1;++i) for(int j=1;j<=n+1;++j) for(int k=1;k<=n+1;++k)
		res.a[i][j]+=x.a[i][k]*y.a[k][j];
	for(int i=1;i<=n+1;++i) for(int j=1;j<=n+1;++j) res.a[i][j]%=mod;
	return res;
}
Matrix qpow(Matrix x,int y)
{
	Matrix res;res.one();
	for(;y;y>>=1,x=x*x) if(y&1) res=res*x;
	return res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4887.in","r",stdin);
	freopen("BZOJ4887.out","w",stdout);
#endif
	n=read();m=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		tran.a[u][v]=tran.a[v][u]=1;
	}
	for(int i=1;i<=n+1;++i) tran.a[i][i]=tran.a[i][n+1]=1;
	T=read();ans.a[1][1]=1;ans=ans*qpow(tran,T+1);
	printf("%d\n",ans.a[1][n+1]);
	return 0;
}

BZOJ4888 异或和

对于位运算题一般按位考虑答案,那么就是求所有和每一位出现 0 0 0的个数。
显然区间和可以转化为前缀差分。
那么对于 s i − s j , j &lt; i s_i-s_j,j&lt;i sisj,j<i,我们对于每一位考虑时,可以分类讨论这一位结果为 0 0 0 1 1 1的充要条件。观察到结果只和低位组成的数字大小有关,而数字和不超过 1 0 6 10^6 106,于是我们对 0 , 1 0,1 0,1分别维护一个 BIT \text{BIT} BIT记录前缀数字出现次数来分类讨论即可。
这样做复杂度是 O ( n log ⁡ 2 c ) O(n\log^2 c) O(nlog2c)的,其中 c c c是所有数的和。

我们还可以多项式学傻了系列:
我们考虑每种权值的出现次数,令 f ( x ) f(x) f(x)表示前缀和的生成函数,那么系数 f i ∗ f j → f i − j f_i*f_j\rightarrow f_{i-j} fifjfij
于是我们将 f ( x ) f(x) f(x)和它倒过来做一个卷积即可。
这样做复杂度是 O ( c log ⁡ c ) O(c\log c) O(clogc)的。
当然跑不过去

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;

typedef long long ll;
const int N=1e6+10;
int n,ans,a[N],fc[22];

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

struct BIT
{
	int c[N];
	void clear(){memset(c,0,sizeof(c));}
	void update(int x){for(;x<N;x+=lowbit(x))c[x]++;}
	int query(int x){int res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
	int qsum(int l,int r){if(l>r)return 0;return query(r)-query(l-1);}
}T0,T1;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4888.in","r",stdin);
	freopen("BZOJ4888.out","w",stdout);
#endif
	n=read();
	for(int i=1;i<=n;++i) a[i]=read()+a[i-1];
	fc[0]=1;for(int i=1;i<20;++i) fc[i]=fc[i-1]<<1;
	
	for(int k=0;k<20;++k)
	{
		T0.clear();T1.clear();ll res=0;
		for(int i=0;i<=n;++i)
		{
			int tmp=a[i]%fc[k]+1;
			if(a[i]&fc[k])
			{
				res+=T0.qsum(1,tmp)+T1.qsum(tmp+1,N-1);
				T1.update(tmp);
			}
			else
			{
				res+=T0.qsum(tmp+1,N-1)+T1.qsum(1,tmp);
				T0.update(tmp);
			}
		} 
		ans+=(res&1)*fc[k];
	}
	printf("%d",ans);
	return 0;
}
#include<bits/stdc++.h>
using namespace std;

typedef double db;
const int N=2097154;
const db pi=acos(-1);
int n,ans,s[N];

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

namespace FFT
{
	int m,L,rev[N];
	struct cd
	{
		db r,i;
		cd(db _r=0,db _i=0):r(_r),i(_i){}
		cd operator +(const cd&a)const{return cd(r+a.r,i+a.i);}
		cd operator -(const cd&a)const{return cd(r-a.r,i-a.i);}
		cd operator *(const cd&a)const{return cd(r*a.r-i*a.i,r*a.i+i*a.r);}
	}a[N],b[N];
	void reget(int n)
	{
		for(m=1,L=0;m<=n*2;m<<=1,++L);
		for(int i=0;i<m;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
	}	
	void fft(cd *a,int n,int f)
	{
		for(int i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
		for(int i=1;i<n;i<<=1)
		{
			cd wn=cd(cos(pi/i),f*sin(pi/i));
			for(int j=0;j<n;j+=i<<1)
			{
				cd w=cd(1,0);
				for(int k=0;k<i;++k,w=w*wn)
				{
					cd x=a[j+k],y=w*a[i+j+k];
					a[j+k]=x+y;a[i+j+k]=x-y;
				}
			}
		}
		if(!~f)for(int i=0;i<n;++i)a[i].r/=n;
	}
}
using namespace FFT;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4888.in","r",stdin);
	freopen("BZOJ4888.out","w",stdout);
#endif
	n=read();a[0].r=1;
	for(int i=1;i<=n;++i) s[i]=read()+s[i-1],++a[s[i]].r;
	for(int i=0;i<=s[n];++i) b[s[n]-i].r=a[i].r;
	reget(s[n]);fft(a,m,1);fft(b,m,1);
	for(int i=0;i<m;++i) a[i]=a[i]*b[i];
	fft(a,m,-1);
	for(int i=0;i<=s[n];++i) if((int)(a[i].r+0.5)&1) ans^=(s[n]-i);
	printf("%d\n",ans);
	return 0;
}

BZOJ4889 不勤劳的图书管理员

对于一次交换产生的影响只是在这个区间内部。
考虑交换的影响,就是区间中比 l l l a l a_l al大的所有数都会产生 v l v_l vl的贡献,比 a l a_l al小的所有数都会产生 − v l -v_l vl的贡献。 r r r类似考虑。
这样就是一个查询一个区间内大于某个数的个数及其权值和的操作。
直接上树套树就行了,第一维区间 BIT \text{BIT} BIT,第二维权值线段树。
复杂度 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;

typedef long long ll;
const int N=5e4+10,M=N*200,mod=1e9+7;
int n,m,a[N],b[N];
ll ans;

namespace IO
{
	int read()
	{
		int ret=0;char c=getchar();
		while(!isdigit(c)) c=getchar();
		while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
		return ret;
	}
	void write(int x)
	{
		if(x>9) write(x/10);
		putchar(x%10^48);
	}
	void writeln(int x){write(x);putchar('\n');}
}

ll upm(ll x){x%=mod;if(x<0)x+=mod;return x;}
void up(ll &x,ll y){x=upm(x+y);}

namespace Tree_up_Tree
{
	int rt[N];
	struct node
	{
		ll val;int cnt,ls,rs;
		node(ll _val=0,int _cnt=0,int _ls=0,int _rs=0):val(_val),cnt(_cnt),ls(_ls),rs(_rs){}
	};
	struct Segment
	{
		node t[M];int sz;
		void update(int &x,int l,int r,int p,int vl,int ct)
		{
			if(!x) x=++sz; t[x].val+=vl;t[x].cnt+=ct;
			if(l==r) return;
			int mid=(l+r)>>1;
			if(p<=mid) update(t[x].ls,l,mid,p,vl,ct);
			else update(t[x].rs,mid+1,r,p,vl,ct);
		}
		ll queryv(int x,int l,int r,int L,int R)
		{
			if(!x) return 0;
			if(L<=l && r<=R) return t[x].val;
			int mid=(l+r)>>1;ll res=0;
			if(L<=mid) res+=queryv(t[x].ls,l,mid,L,R);
			if(R>mid) res+=queryv(t[x].rs,mid+1,r,L,R);
			return res;
		}
		int queryc(int x,int l,int r,int L,int R)
		{
			if(!x) return 0;
			if(L<=l && r<=R) return t[x].cnt;
			int mid=(l+r)>>1,res=0;
			if(L<=mid) res+=queryc(t[x].ls,l,mid,L,R);
			if(R>mid) res+=queryc(t[x].rs,mid+1,r,L,R);
			return res;
		}
	}tr;

	struct BIT
	{	
		void update(int x,int p,int vl,int ct){for(;x<=n;x+=lowbit(x))tr.update(rt[x],1,n,p,vl,ct);}
		ll queryv(int l,int r,int L,int R)
		{
			if(l>r || L>R) return 0;
			ll res=0;
			for(;r;r-=lowbit(r)) res+=tr.queryv(rt[r],1,n,L,R);
			for(--l;l;l-=lowbit(l)) res-=tr.queryv(rt[l],1,n,L,R);
			return res;
		}
		int queryc(int l,int r,int L,int R)
		{
			if(l>r || L>R) return 0;
			int res=0;
			for(;r;r-=lowbit(r)) res+=tr.queryc(rt[r],1,n,L,R);
			for(--l;l;l-=lowbit(l)) res-=tr.queryc(rt[l],1,n,L,R);
			return res;
		}
	}bit;
	void solve()
	{
		for(int i=1;i<=n;++i) bit.update(i,a[i],b[i],1);
		while(m--)
		{
			int l=IO::read(),r=IO::read();if(l>r) swap(l,r);
			if(l==r) {IO::writeln(ans);continue;}
			up(ans,bit.queryv(l+1,r-1,1,a[r]-1));
			up(ans,(ll)bit.queryc(l+1,r-1,1,a[r]-1)*b[r]);
			up(ans,-bit.queryv(l+1,r-1,a[r]+1,n));
			up(ans,(ll)-bit.queryc(l+1,r-1,a[r]+1,n)*b[r]);
			up(ans,bit.queryv(l+1,r-1,a[l]+1,n));
			up(ans,(ll)bit.queryc(l+1,r-1,a[l]+1,n)*b[l]);
			up(ans,-bit.queryv(l+1,r-1,1,a[l]-1));
			up(ans,(ll)-bit.queryc(l+1,r-1,1,a[l]-1)*b[l]);
			up(ans,(ll)(a[l]<a[r]?1:-1)*(b[l]+b[r]));
			bit.update(l,a[l],-b[l],-1);bit.update(l,a[r],b[r],1);
			bit.update(r,a[r],-b[r],-1);bit.update(r,a[l],b[l],1);
			swap(a[l],a[r]);swap(b[l],b[r]);
			IO::writeln(ans);
		}
	}
}

namespace BIT
{
	struct BIT
	{
		ll val[N];int cnt[N];
		void update(int x,int v){for(;x<=n;x+=lowbit(x))val[x]+=v,++cnt[x];}
		ll queryc(int x){ll res=0;for(;x;x-=lowbit(x))res+=cnt[x];return res;}
		ll queryv(int x){ll res=0;for(;x;x-=lowbit(x))res+=val[x];return res;}
	}bit;
	void initans()
	{
		for(int i=n;i;--i) 
			bit.update(a[i],b[i]),up(ans,bit.queryv(a[i]-1)+(ll)bit.queryc(a[i]-1)*b[i]);
	}
}

void init()
{
	n=IO::read();m=IO::read();
	for(int i=1;i<=n;++i) a[i]=IO::read(),b[i]=IO::read();
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4889.in","r",stdin);
	freopen("BZOJ4889.out","w",stdout);
#endif
	init();
	BIT::initans();
	Tree_up_Tree::solve();
	return 0;
}

BZOJ4890 城市

枚举删去哪条边,求出两棵树的带权重心,那么最优加边一定是在两个带权重心之间,再和两棵树的直径作比较。选取所有情况下最优值。复杂度 O ( n 2 ) O(n^2) O(n2)

#include<bits/stdc++.h>
using namespace std;

const int N=5005,INF=1e9;
int n,ans,tot,ban,rt1,rt2;
int head[N],fr[N],dis[N];
queue<int>q;

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

struct Tway{int v,w,nex;}e[N<<1];
void add(int u,int v,int w)
{
	e[++tot]=(Tway){v,w,head[u]};head[u]=tot;
	e[++tot]=(Tway){u,w,head[v]};head[v]=tot;
}
void bfs(int &rt)
{
	q.push(rt);fr[rt]=dis[rt]=0;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=head[x];i;i=e[i].nex)
		{
			int v=e[i].v;
			if(~dis[v] || i==ban || i==(ban^1)) continue;
			dis[v]=dis[x]+e[i].w;fr[v]=x;q.push(v);
			if(dis[v]>dis[rt]) rt=v;
		}
	}
}
int getlen(int x)
{
	int rt=x,res=INF;
	for(;x;x=fr[x]) res=min(res,max(dis[x],dis[rt]-dis[x]));
	return res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4890.in","r",stdin);
	freopen("BZOJ4890.out","w",stdout);
#endif
	ans=INF;tot=1;n=read();
	for(int i=1,u,v,w;i<n;++i) u=read(),v=read(),w=read(),add(u,v,w);
	for(int i=2;i<n*2;i+=2)
	{
		ban=i;rt1=e[i].v;rt2=e[i^1].v;
		//printf("cut:%d %d %d\n",rt1,rt2,e[i].w);
		memset(dis,-1,sizeof(dis));bfs(rt1);bfs(rt2);
		memset(dis,-1,sizeof(dis));bfs(rt1);bfs(rt2);
		//printf("rt:%d %d dis:%d %d\n",rt1,rt2,dis[rt1],dis[rt2]);
		int tmpans=max(dis[rt1],dis[rt2]);
		int len1=getlen(rt1),len2=getlen(rt2);
		//printf("half:%d %d\n",len1,len2);
		tmpans=max(tmpans,len1+len2+e[i].w);
		ans=min(ans,tmpans);
	}
	printf("%d\n",ans);
	return 0;
}

BZOJ4891 龙舟

一种显然的暴力是分解质因数后约分,再判断分母是否与模数互质。
这样做的复杂度是 O ( m ( M + log ⁡ M ) ) O(m(\sqrt M +\log M)) O(m(M +logM))的(这里 a i a_i ai M M M同阶)。
考虑瓶颈在分解质因数,于是我们只需要写一个 pollard-rho \text{pollard-rho} pollard-rho就可以过了。
最后的复杂度就是 O ( m ( M 1 4 + log ⁡ M ) ) O(m(M^{\frac 1 4}+\log M)) O(m(M41+logM))
需要用到快速乘,一定要用long double,不然就凉了。

#include<bits/stdc++.h>
using namespace std;

typedef long double ldb;
typedef long long ll;
const ll N=1e4+10;
const ldb eps=1e-8;
ll pnum,n,m,K;
ll a[22][N],b[N],pri[N],num0[N],num[N];

ll read()
{
	ll ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

namespace Divide_Prime
{
	ll mul(ll x,ll y,ll mod){return ((x*y-(ll)((ldb)x/mod*y+eps)*mod)%mod+mod)%mod;}
	ll qpow(ll x,ll y,ll mod)
	{
		ll res=1;
		for(;y;y>>=1,x=mul(x,x,mod))if(y&1)res=mul(res,x,mod);
		return res;
	}
	bool checkpri(ll a,ll y,int cnt,ll mod)
	{
		ll x=qpow(a,y,mod);if(x==1 || x==mod-1) return 1;
		for(int i=1;i<=cnt;++i)
		{
			x=mul(x,x,mod);
			if(x==1) return 0;
			if(x==mod-1) return 1;
		}
		return 0;
	}
	bool miller_rabin(ll x)
	{
		if(x==2) return 1;
		if(x%2==0) return 0;
		ll y=x-1;int cnt=0;
		while(y%2==0) y>>=1,++cnt;
		for(int i=1;i<=5;++i) if(!checkpri(rand()%(x-2)+1,y,cnt,x)) return 0;
		return 1;
	}
	ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
	ll pollard_rho(ll a,ll mod)
	{
		ll x=rand()%mod,y=x,k=2,g=1;
		for(int i=1;g==1;++i)
		{
			x=(mul(x,x,mod)+a)%mod;
			g=gcd(abs(x-y),mod);
			if(i==k){k<<=1;y=x;}
		}
		return g;
	}
	void divide(ll x)
	{
		//cerr<<x<<endl;
		if(x==1) return;
		if(miller_rabin(x)){pri[++pnum]=x;return;}
		ll t=x;while(t==x)t=pollard_rho(rand()%(x-1)+1,x);
		divide(t);divide(x/t);
	}
}
using namespace Divide_Prime;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4891.in","r",stdin);
	freopen("BZOJ4891.out","w",stdout);
#endif
	srand(19260817);
	n=read();m=read();K=read();
	for(int i=1;i<=m;++i) b[i]=read();
	for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) a[i][j]=read();
	while(K--)
	{
		ll id=read(),mod=read();pnum=0;divide(mod);
		sort(pri+1,pri+pnum+1);
		//for(int i=1;i<=pnum;++i) cerr<<pri[i]<<" ";cerr<<endl;
		ll cnt=0,phi=mod;
		for(int i=1;i<=pnum;++i) 
		{
			if(pri[i]^pri[i-1]) pri[++cnt]=pri[i],phi-=phi/pri[i],num0[cnt]=num[cnt]=0;
			++num0[cnt];
		}
		ll ans=1,inv=1;
		for(int i=1;i<=m;++i)
		{
			ll x=b[i];
			for(int j=1;j<=cnt;++j) while(!(x%pri[j])) x/=pri[j],++num[j];
			ans=mul(ans,x,mod);
		}
		for(int i=1;i<=m;++i)
		{
			ll x=a[id][i];
			for(int j=1;j<=cnt;++j) while(!(x%pri[j])) x/=pri[j],--num[j];
			inv=mul(inv,x,mod);
		}
		bool fg=1;
		for(int i=1;i<=cnt;++i) if(num[i]<0){puts("-1");fg=0;break;}
		if(!fg) continue;
		for(int i=1;i<=cnt;++i) if(num[i]) ans=mul(ans,qpow(pri[i],num[i],mod),mod);
		ans=mul(ans,qpow(inv,phi-1,mod),mod);
		printf("%lld\n",ans);

	}
	return 0;
}

BZOJ4892 DNA

枚举开头位置暴力 L C P LCP LCP即可。
顺便研究了一下后缀数组的板子。
复杂度 O ( T n log ⁡ n ) O(Tn\log n) O(Tnlogn)
或者这个东西相当于求每一位开始匹配有多少位不同,显然可以用 FFT \text{FFT} FFT来做,复杂度是一样的。
可是还是跑不过

#include<bits/stdc++.h>
using namespace std;

const int N=2e5+10;
int T,a[N];
char s[N],t[N];

namespace SA
{
	int sa[N],rk[N],hi[N],h[20][N];
	int wa[N],wb[N],wx[N],wy[N];
	int remn,Log[N],fc[20];
	bool cmp(int *r,int a,int b,int l){return r[a]==r[b] && r[a+l]==r[b+l];}
	void getsa(int *r,int n,int m)
	{
		int *x=wa,*y=wb,*t,i,j,p;
		for(i=0;i<m;++i) wx[i]=0;
		for(i=0;i<n;++i) wx[x[i]=r[i]]++;
		for(i=1;i<m;++i) wx[i]+=wx[i-1];
		for(i=n-1;~i;--i) sa[--wx[x[i]]]=i;
		for(j=1,p=0;p<n;j<<=1,m=p)
		{
			for(p=0,i=n-j;i<n;++i) y[p++]=i;
			for(i=0;i<n;++i) if(sa[i]>=j) y[p++]=sa[i]-j;
			for(i=0;i<m;++i) wx[i]=0;
			for(i=0;i<n;++i) wx[wy[i]=x[y[i]]]++;
			for(i=1;i<m;++i) wx[i]+=wx[i-1];
			for(i=n-1;~i;--i) sa[--wx[wy[i]]]=y[i];
			for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)
				x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
		}
	}
	void getheight(int *r,int n)
	{
		int i,j,k=0;
		for(i=1;i<=n;++i) rk[sa[i]]=i;
		for(i=0;i<n;hi[rk[i++]]=k)
			for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];++k);
	}
	void adjust(int n)
	{
		for(int i=1;i<=n;++i) sa[i]++;
		for(int i=n;i;--i) rk[i]=rk[i-1];
		sa[0]=rk[0]=0;
	}
	void initrmq(int n)
	{
		for(int i=1;i<=n;++i) h[0][i]=hi[i];
		for(int j=1;j<20;++j) for(int i=1;i+fc[j]-1<=n;++i)
			h[j][i]=min(h[j-1][i],h[j-1][i+fc[j-1]]);
	}
	void initsa(int *r,int n)
	{
		remn=n;
		getsa(r,n+1,30);getheight(r,n);adjust(n);initrmq(n);
	}
	int calc(int l,int r){int t=Log[r-l+1];return min(h[t][l],h[t][r-fc[t]+1]);}
	int lcp(int x,int y){x=rk[x];y=rk[y];if(x>y)swap(x,y);return calc(x+1,y);}
	void clear(){memset(sa,0,(remn+2)<<2);memset(rk,0,(remn+2)<<2);memset(hi,0,(remn+2)<<2);}
	void initLog()
	{
		Log[1]=0;for(int i=2;i<N;++i)Log[i]=Log[i>>1]+1;
		fc[0]=1;for(int i=1;i<20;++i) fc[i]=fc[i-1]<<1;
	}
}
using SA::lcp;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("BZOJ4892.in","r",stdin);
	freopen("BZOJ4892.out","w",stdout);
#endif
	scanf("%d",&T);SA::initLog();
	while(T--)
	{
		scanf("%s%s",s,t);
		int tn=strlen(s),n=tn,len=strlen(t);
		if(n<len){puts("0");continue;}
		s[n++]='Z'+1;
		for(int i=0;i<len;++i) s[n++]=t[i];
		for(int i=0;i<n;++i) a[i]=s[i]-'A'+1;
		SA::clear();SA::initsa(a,n);//SA::output();

		int ans=0;
		for(int i=1;i+len-1<=tn;++i)
		{
			//printf("beg:%d\n",i);
			int now=tn+lcp(i,tn+2)+1,k;
			if(now==n) {++ans;continue;}
			//printf("%d\n",now);
			for(k=1;k<=3;++k)
			{
				now+=2;
				if(now>n) {++ans;break;}
				//printf("cmp:%d %d ",now-tn-1+i-1,now);
				now=now+lcp(now-tn-1+i-1,now)-1;
				//printf("goto:%d \n",now);
				if(now==n) {++ans;break;}
			}
			//puts("");
		}
		printf("%d\n",ans);
	}
	//cerr<<clock()<<endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值