I.Substring
题意:找出最大的集合内串互不同构的子串的集合的大小.
因为串内字符只存在
所以我们暴力处理出原串的所有同构串,并重构一个包含原串所有同构的新串,新串的长度为原串的长度
那么对于这个问题就转化成了计算新串中不同的子串的个数,这个问题用SA或是SAM都可以解决
由于蒟蒻只会SA,下面的代码上的就是SA解题版.
在我们算出的不同(SA算出的是不同的子串,不是不同构!)的子串的中有两种串
第一类形如
只存在中的一种字符
除此以外的串都算作第二类
显然可知,对于第一类串,同构的串存在种,而对于第二类串,同构的串存在种
我们定义不同的串的个数为,第一类串的个数为
那么显然便可以得到我们所要的结果
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define inf int(0x3f3f3f3f)
#define mod ll(1e9+7)
#define eps double(1e-7)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
#define maxn 50005*6
#define rank Rank
int n,pos;
int tot;
ll wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
ll rank[maxn],height[maxn],s[maxn];
char str[maxn];
bool cmp(ll *r,int a,int b,int k)
{
return r[a]==r[b]&&r[a+k]==r[b+k];
}
void get_sa(ll *r,ll *sa,int n,int m)
{
ll i,j,p,*x=wa,*y=wb,*t;
for(i=0; i<m; i++)
wsf[i]=0;
for(i=0; i<n; i++)
wsf[x[i]=r[i]]++;
for(i=1; i<m; i++)
wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--)
sa[--wsf[x[i]]]=i;
p=1;
j=1;
for(; p<n; j*=2,m=p)
{
for(p=0,i=n-j; i<n; i++)
y[p++]=i;
for(i=0; i<n; i++)
if(sa[i]>=j)
y[p++]=sa[i]-j;
for(i=0; i<n; i++)
wv[i]=x[y[i]];
for(i=0; i<m; i++)
wsf[i]=0;
for(i=0; i<n; i++)
wsf[wv[i]]++;
for(i=1; i<m; i++)
wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--)
sa[--wsf[wv[i]]]=y[i];
t=x;
x=y;
y=t;
x[sa[0]]=0;
for(p=1,i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
}
}
void get_height(ll *r,int n)
{
int i,j,k=0;
for(i=0; i<n; i++)
rank[sa[i]]=i;
for(i=0; i<n; i++)
{
if(k)
k--;
else
k=0;
j=sa[rank[i]-1];
while(r[i+k]==r[j+k])
k++;
height[rank[i]]=k;
}
}
ll cal_s_mul()
{
ll ans=0;
ll pre=0;
for(int i=0; i<pos; i++)
{
ans+=n-(sa[i]%(n+1))-min(height[i],min(pre,n-(sa[i]%(n+1))));
pre=n-(sa[i]%(n+1));
}
return ans;
}
ll cal_s_sg()
{
ll ans=0;
ll cnt=1;
for(int i=1;i<n;i++)
{
if(str[i]!=str[i-1])
ans=max(ans,cnt),cnt=1;
else
cnt++;
}
ans=max(ans,cnt);
return ans*3ll;
}
void ex_to(int a,int b,int c)
{
for(int i=0; i<n; i++)
{
if(str[i]=='a')
s[pos++]=a;
else if(str[i]=='b')
s[pos++]=b;
else
s[pos++]=c;
}
s[pos++]=0;
}
void op()
{
int ss[5];
for(int i=0; i<3; i++)
ss[i]=i+1;
pos=0;
do
{
ex_to(ss[0],ss[1],ss[2]);
}
while(next_permutation(ss,ss+3));
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while(cin>>n)
{
cin>>str;
op();
get_sa(s,sa,pos,130);
get_height(s,pos);
ll ans=cal_s_mul();
ans=(ans-cal_s_sg())/6ll+cal_s_sg()/3ll;
cout<<ans<<endl;
}
}