萌新求助
查看原帖
萌新求助
601747
xibaohe楼主2023/10/3 08:41

KMP+同余最短路die码求调,思路上与第1篇题解相似,从早上起来一直调到现在,谁能帮忙调一下,悬2-3关

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<list>
#include<queue>
#include<deque>
#include<map>
using namespace std;
#define int long long
#define endl '\n'
#define MAXN 1000005
#define INF 0x3f3f3f3f3f3f3f3f
string s;
int T,n,m,l,cnt,tp,nn,tmp,a[MAXN],nxt[MAXN],bord[MAXN],r[MAXN],pos[MAXN],se[MAXN],st[MAXN],q[MAXN],ans=0;
void Ios()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout.flags(ios::fixed);
   	cout.precision(6);
    return;
}
void MODE(int len,int b,int d)//同余最短路 
{
	int cnt1=__gcd(b,d),cnt2=__gcd(b,nn);
	for(int i=0;i<n;i++) r[i]=a[i];
	for(int i=0;i<b;i++) a[i]=INF;
	for(int i=0;i<nn;i++) tmp=r[i]%b,a[tmp]=min(a[tmp],r[i]);
	for(int i=0;i<cnt2;i++)
	{
		tp=0;
		q[++tp]=i;
		int tmp=(i+nn)%b;
		while(tmp!=q[1]) q[++tp]=tmp,tmp=(tmp+nn)%b;
		for(int j=tp+1;j<=2*tp;j++) q[j]=q[j-tp];
		tp*=2;;
		for(int j=2;j<=tp;j++) a[q[j]]=min(a[q[j]],a[q[j-1]]+nn);
	}
	nn=b;
	if(d<0) return;
	for(int i=0;i<cnt1;i++)
	{
		int tp=0;
		q[++tp]=i;
		int tmp=(i+d)%b;
		while(tmp!=q[1]) q[++tp]=tmp,tmp=(tmp+d)%b;
		int mp=1;
		for(int j=1;j<=tp;j++) if(a[q[j]]<a[q[mp]]) mp=j;
		int tmp_cnt1=0;
		for(int j=mp;j<=tp;j++) se[++tmp_cnt1]=q[j];
		for(int j=1;j<mp;j++) se[++tmp_cnt1]=q[j];
		int low=1,high=1;
		pos[1]=1;
		st[1]=a[se[1]]-d;
		for(int j=2;j<=tp;j++)
		{
			while(low<=high&&pos[low]+len<j) low++;
			if(low<=high) a[se[j]]=min(a[se[j]],st[low]+j*d+b);
			while(low<=high&&st[high]>=a[se[j]]-j*d)high--;
			st[++high]=a[se[j]]-j*(long long)d,pos[high]=j;
		}
	}
}


signed main()
{
	Ios();
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		m-=n;
		cin>>s;
		l=s.size();
		nxt[0]=0,nxt[1]=0;
		for(int q=1,k=0;q<l;q++)//KMP 
		{
			k=nxt[q];
			while(k&&s[k]!=s[q]) k=nxt[k];
			if(s[k]==s[q]) k++;
			nxt[q+1]=k;
		}
		int p=nxt[l];
		while(p>0)
		{
			bord[++cnt] =l-p;
			p=nxt[p];
		}
		bord[++cnt]=l;
		memset(a,0x3f,sizeof(a));;
		nn=n;
		for(int i=1,k=1;i<=cnt;)
		{
			while(bord[k+1]+bord[i]==bord[i+1]+bord[k]) k++;
			MODE(k-i-1,bord[i],bord[i+1]-bord[i]);
			i=k;
		}
		for(int i=0;i<nn;i++) if(a[i]<=m) ans=ans+(m-a[i])/nn+1;
		cout<<ans<<endl;
		ans=cnt=0;
	}
	
	return 0;
}







QAQ

2023/10/3 08:41
加载中...