题目连接:https://ac.nowcoder.com/acm/contest/9984/B
分析
如果 s 串和 t 串从第一位到第 x 位是相同的,那么再看 t 串从 x + 1 位开始和 s 串的前缀最多有多少相同长度,那么 ans 就可以加上多少。
比较字符串我们可以用哈希值来做,查找最长的相同长度可以用二分法。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5;
const double esp=1e-6;
const ll mod=1e9+7;
const int base = 233;
int n,m,op;
char s[N],t[N];
ull h1[N],h2[N],p[N];
ll qpow(ll a,ll b){
ll ans=1,base=a;
while(b){
if(b&1) ans=ans*base%mod;
base=base*base%mod;
b>>=1;
}
return ans;
}
ull get_hash(ull h[],int len,int l,int r){
if(r>len) return 0;
return h[r]-h[l-1]*p[r-l+1];
}
void solve(){
scanf("%s %s",s+1,t+1);
int l1=strlen(s+1),l2=strlen(t+1);
p[0]=1;
for(int i=1;i<=l1;i++){
h1[i]=h1[i-1]*base+s[i];
p[i]=p[i-1]*base;
}
for(int i=1;i<=l2;i++){
h2[i]=h2[i-1]*base+t[i];
if(i>=l1) p[i]=p[i-1]*base;
}
ll res = 0;
for(int i=1;i<=l2;i++){
if(s[i]!=t[i]) break;
if(s[1]!=t[i+1]) continue;
int l=1,r=l1;
while(l<r){
int mid=(l+r+1)/2;
ull t1=get_hash(h1,l1,1,mid);
ull t2=get_hash(h2,l2,i+1,i+mid);
if(t1==t2) l=mid;
else r=mid-1;
}
res+=l;
}
printf("%lld",res);
}
int main(){
int Case=1;
//init();
//scanf("%d",&Case);
while(Case--){
solve();
}
return 0;
}