題目大意:
len(Ti)+len(Tj)枚舉一下就好,主要是如何算sigma{lcp(Ti,Tj)}
將原串反過來建後綴自動機,兩個節點的lca即最長子串就是這兩個節點代表的串的lcp
於是枚舉、DP一下即可
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 500005
using namespace std;
typedef long long LL;
struct Node {
Node *ch[26],*pa;
int val,cnt,siz;
bool vis;
Node() {}
Node(int _val):val(_val),cnt(0),siz(0),pa(NULL),vis(false) {
memset(ch,0,sizeof ch);
}
void* operator new(size_t) {
static Node *C,*mempool;
if(C==mempool) mempool=(C=new Node[1<<20])+(1<<20);
return C++;
}
}*root=new Node(0),*last;
void extend(char c) {
int z=c-'a';
Node *p=last,*np=new Node(p->val+1);
last=np;
while(p && !p->ch[z]) p->ch[z]=np, p=p->pa;
if(!p) {
np->pa=root;
return ;
}
Node* q=p->ch[z];
if(q->val==p->val+1) {
np->pa=q;
return ;
}
Node* nq=new Node(p->val+1);
nq->pa=q->pa;
q->pa=np->pa=nq;
memcpy(nq->ch,q->ch,sizeof nq->ch);
while(p && p->ch[z]==q) p->ch[z]=nq, p=p->pa;
return ;
}
void init(char s[]) {
last=root;
int len=strlen(s);
Node* o=root;
for(int i=0;i<len;i++)
extend(s[i]), o=o->ch[s[i]-'a'], o->siz++, o->cnt++;
return ;
}
LL solve() {
static Node *q[N*2],*s[N*2];
static int t[N];
LL tmp=0;
int l=0,r=0;
q[r++]=root;
while(l<r) {
Node* o=q[l++];
t[o->val]++;
for(int i=0;i<26;i++)
if(o->ch[i] && !o->ch[i]->vis)
q[r++]=o->ch[i], o->ch[i]->vis=true;
}
for(int i=1;i<=r;i++) t[i]+=t[i-1];
for(int i=r-1;~i;i--) s[t[q[i]->val]--]=q[i];
for(int i=r;i;i--)
if(s[i]->pa)
s[i]->pa->siz+=s[i]->siz;
for(int i=1;i<r;i++) {
tmp+=(LL)q[i]->pa->cnt*q[i]->siz*q[i]->pa->val;
q[i]->pa->cnt+=q[i]->siz;
}
return tmp;
}
int main() {
static char s[N],str[N];
scanf("%s",str);
int len=strlen(str);
for(int i=0;i<len;i++) s[i]=str[len-i-1];
init(s);
LL ans=0;
for(int i=0;i<len;i++) ans+=(LL)(i+1)*(len-1);
printf("%lld\n",ans-solve()*2);
return 0;
}