爆零求助
  • 板块P6216 回文匹配
  • 楼主lao_lihiOI
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/2/27 02:08
  • 上次更新2023/10/28 07:39:03
查看原帖
爆零求助
317650
lao_lihiOI楼主2022/2/27 02:08

思路是前缀和维护前缀和,sum[0][i]维护的是以i为右端点的s2出现次数,sum[1]维护的是sum[0]的前缀和。求调错 or hack

#include<bits/stdc++.h>
#define rep(a,b,c) for(int a=b;a<=c;a++)
using namespace std;
typedef long long ll;
const int MAXN=3e6+5;
int n,m,mid,mr,p[MAXN],nxt[MAXN];
ll sum[2][MAXN];
string a,b;
unsigned int ans;
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	cin>>a>>b;
	n=a.length(),m=b.length();
	a=' '+a,b=' '+b;
	int j=0;
	rep(i,2,m){
		while(j&&b[j+1]!=b[i])j=nxt[j];
		if(b[j+1]==b[i])j++;
		nxt[i]=j;
	}
	j=0;
	rep(i,1,n){
		while(j&&b[j+1]!=a[i])j=nxt[j];
		if(b[j+1]==a[i])j++;
		sum[0][i]=sum[0][i-1];
		if(j==m)sum[0][i]++,j=0;
	}
	rep(i,1,n)sum[1][i]=sum[1][i-1]+sum[0][i];
	
	rep(i,1,n){
		if(i<=mr)p[i]=min(mr-i+1,p[mid*2-i]);
		while(a[i-p[i]]==a[i+p[i]])p[i]++;
		if(i+p[i]>mr)mr=i+p[i]-1,mid=i;
		p[i]--;
	}
	rep(i,1,n){
		if(p[i]*2+1<m)continue;
		ans+=sum[1][min(i+p[i],n)]-sum[1][max(i+m/2-1,0)]-(sum[1][max(i-m/2+m-2,0)]-sum[1][max(i-p[i]+m-3,0)]);
		//cout<<i<<' '<<ans<<endl;
		//cout<<"xx  "<<sum[1][i+p[i]]<<' '<<sum[1][i+m/2-1]<<' '<<sum[1][i-m/2+m-2]<<' '<<sum[1][i-p[i]+m-2]<<endl;
	}
//	cout<<endl;
//	rep(i,1,n)cout<<sum[0][i]<<' ';
//	cout<<endl;
//	rep(i,1,n)cout<<sum[1][i]<<' ';
//	cout<<endl;
	cout<<ans<<endl;
	return 0;
}

2022/2/27 02:08
加载中...