赛时糊的自动机。大概思路是处理 toi,c 表示 i 这个位置再接受一个字符 c 之后,最近的可以全消区间的左端点。
写出来很抽象,虽然过了自测但是完全不明白到底对不对,有没有大佬能鉴定一下/yun
#include <bits/stdc++.h>
#define MAXN 100005
#define foru(a,b,c) for(int (a)=(b);(a)<=(c);(a)++)
#define LL long long
using namespace std;
LL ans;
int n,a[2000005];
int dp[2000005];
int to[2000005][27];
int main(){
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
cin>>n;
foru(i,1,n){
char c=getchar();
while(c<'a' || c>'z') c=getchar();
a[i]=c-'a'+1;
}
for(int i=1;i<=n;i++){
to[i][a[i]]=i;
int j=to[i-1][a[i]];
if(j==0){
continue;
}
dp[i]=dp[j-1]+1;
for(int k=1;k<=26;k++){
if(k!=a[i]) to[i][k]=to[j-1][k];
}
ans+=(LL)dp[i];
}
cout<<ans;
return 0;
}