P3426 哈希做法,WA 60分,求调
查看原帖
P3426 哈希做法,WA 60分,求调
697299
hamster000楼主2024/7/30 08:17
//首先印章必须是border
//其次,如果一个印章的border长度是自身的一半以上
//那么这个印章不必考虑,因为,所以要考虑的印章只有log n个
//对于每个可能的印章,利用哈希线性确认能否满足题目条件。
#include <bits/stdc++.h>

const int maxn=500005;
std::string s;
int nxt[maxn],f[maxn];
const int mod=1e9+7;
typedef long long ull;
ull base=131;
ull hash[maxn],B[maxn],back_up;

ull gethash(int l,int r){
	return (hash[r]-hash[l-1]*B[r-l+1]%mod+mod)%mod;
}

std::vector<int> Template;
int main(){

	std::cin >> s;
	int n=s.length();
	//std::cout << n << std::endl;
	B[0]=1;
	s='\0'+s;
	for(int i=1;i<=n;i++){
		B[i]=B[i-1]*base%mod;
		hash[i]=hash[i-1]*base+(s[i]-'a'+1)%mod;
	}
	
	nxt[0]=-1;
	nxt[1]=0;
	int j=0;
	for(int i=2;i<=n;i++){
		while(j>=0&&s[i]!=s[j+1]){
			j=nxt[j];
		}
		nxt[i]=++j;
		//std::cout << nxt[i] << ' ';
	}
	//std::cout << "-------";
	int k=n;
	while(k>0){
		if(nxt[k]*2>=k){
			k=nxt[k];
			continue ;
		}
		//std::cout << k << std::endl;
		Template.push_back(k);
		k=nxt[k];
		
	}
	int ans=Template[0];
	
	for(auto i:Template){
		back_up=0;
		//std::cout << i << std::endl;
		std::string t=s.substr(1,i);
		t='\0'+t;
		
		for(int j=1;j<=i;j++){
			back_up=back_up*base+(t[j]-'a'+1)%mod;
			//std::cout << back_up << std::endl;
		}
		//std::cout << std::endl;
//		int m=t.length();
		bool flag=1;int j=1;
		for(;j+i-1<=n;){
			int k=i;
			std::string p=s.substr(j,i);
			//std::cerr<<p <<' '<<t<<'\n';
			ull x=gethash(j,j+i-1)%mod;
			//本意是判断两个字符串是否相等,如果不相等就跳border
			while(j+i-1<=n&&j>0&&k>0&&x==back_up){
				//std::cout << back_up << ' ' << x << std::endl;
				p=s.substr(j,i);
				//std::cout << j <<' ' << j+i-1<< ' ' << gethash(j,j+i-1) << ' ' << back_up << std::endl;
				k=nxt[k];
				j-=k-1;
				x=gethash(j,j+i-1)%mod;
			}
			if(k<=0){
				flag=0;
				break;
			}
			j+=i;
		}
		
		if(flag){
			ans=std::min(ans,i);
			//std::cout << ans << std::endl;
		}
		
	}
	std::cout << ans << std::endl;
}

各位大佬调试中可能用到的中间结果已经加上。

希望各位巨佬帮忙调试一下,我已经从0分改到60分了,。

2024/7/30 08:17
加载中...