//首先印章必须是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分了,。