除草、切了道水题
给定一个字符串和一个字符,求包含该字符的本质不同的字串个数
sa上对height和字符位置取个max加加就没了
#include<bits/stdc++.h>
#define rank _rank
using namespace std;
const int maxn=1e5+5;
int a[maxn],sa[maxn],rank[maxn],height[maxn];
void build_sa(int n){
static int x[maxn],y[maxn],c[maxn];
int m=26,k=1;
memset(c,0,sizeof(*c)*(m+1));
for(int i=1;i<=n;i++)c[x[i]=a[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i;i--)sa]--]=i;
for(;k<=n;k<<=1){
int tot=k;
for(int i=n-k+1;i<=n;i++)y[i-n+k]=i;
for(int i=1;i<=n;i++)
if(sa[i]>k)y[++tot]=sa[i]-k;
memset(c,0,sizeof(*c)*(m+1));
for(int i=1;i<=n;i++)c[x[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i;i--)sa]]--]=y[i];
for(int i=1;i<=n;i++)y[i]=x[i];
tot=1;x[sa[1]]=1;
for(int i=2;i<=n;i++){
if(max(sa[i],sa[i-1])+k>n
||y[sa[i]]!=y[sa[i-1]]
||y[sa[i]+k]!=y[sa[i-1]+k])
tot++;
x[sa[i]]=tot;
}
if(tot==n)break;else m=tot;
}
for(int i=1;i<=n;i++)rank[sa[i]]=i;
for(int i=1;i<=n;i++){
height[rank[i]]=max(0,height[rank[i-1]]-1);
if(rank[i]==1)continue;
int j=sa[rank[i]-1];
while(max(i,j)+height[rank[i]]<=n
&&a[i+height[rank[i]]]==a[j+height[rank[i]]])
height[rank[i]]++;
}
}
char s[maxn],ss;
int main(){
int T;
scanf("%d",&T);
while(T--){
cin>>ss;
scanf("%s",s+1);
int n=strlen(s+1);
vector<int>vec;
for(int i=1;i<=n;i++){
a[i]=s[i]-'a';
if(s[i]==ss)
vec.push_back(i);
}
build_sa(n);
long long ans=0;
for(int i=1;i<=n;i++){
int x=height[i];
int len=n-sa[i]+1;
int p=lower_bound(vec.begin(),vec.end(),sa[i])-vec.begin();
if(p==vec.size())continue;
x=max(x,vec[p]-sa[i]);
ans+=len-x;
}
static int t=0;
printf("Case #%d: ",++t);
cout<<ans<<endl;
}
return 0;
}