鏈接:https://ac.nowcoder.com/acm/contest/884/I
時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 524288K,其他語言1048576K
64bit IO Format: %lld
題目描述
We call a,ba,ba,b non-equivalent if and only if a≠ba \neq ba=b and a≠rev(b)a \neq rev(b)a=rev(b), where rev(s)rev(s)rev(s) refers to the string obtained by reversing characters of sss, for example rev(abca)=acbarev(abca)=acbarev(abca)=acba.
There is a string sss consisted of lower-case letters. You need to find some substrings of sss so that any two of them are non-equivalent. Find out what's the largest number of substrings you can choose.
輸入描述:
A line containing a string sss of lower-case letters.
輸出描述:
A positive integer - the largest possible number of substrings of sss that are non-equivalent.
示例1
輸入
abac
輸出
8
說明
The set of following substrings is such a choice: abac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,c.
題意:對於給出的一個串,找出本質不同的串,同時這些本質不同的串的反轉串不能和其他的串的原串一樣
題解:在一個後綴自動機上建立原串和反轉串,然後就可以求本質不同的串p,但這樣本身是迴文串的會被算少一次,所以我們需要用迴文輸算出這個串的本質不同的迴文串的數目q,然後(p+q)/2就是答案了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+9;
char s[maxn];
int vis[maxn];
struct SAM{
int len[maxn<<1],link[maxn<<1],ch[maxn<<1][26];
int num[maxn<<1];
int sz,rt,last;
int newnode(int x=0){
len[sz]=x;
link[sz]=-1;
memset(ch[sz],-1,sizeof(ch[sz]));
return sz++;
}
void init(){sz=last=0,rt=newnode();}
void reset(){last=0;}
void extend(int c){
int np=newnode(len[last]+1);
int p;
for(p=last;~p&&ch[p][c]==-1;p=link[p])ch[p][c]=np;
if(p==-1){
link[np]=rt;
}
else{
int q=ch[p][c];
if(len[p]+1==len[q]){
link[np]=q;
}
else{
int nq=newnode(len[p]+1);
memcpy(ch[nq],ch[q],sizeof(ch[q]));
link[nq]=link[q],link[q]=link[np]=nq;
for(;~p&&ch[p][c]==q;p=link[p])ch[p][c]=nq;
}
}
last=np;
}
}sam;
struct Palindromic_Tree{
struct Node{
int son[26];
int ff,len;
}t[maxn];
int last,tot;
void init(){
t[++tot].len=-1;
t[0].ff=t[1].ff=1;
}
void extend(int c,int n){
int p=last;
while(s[n-t[p].len-1]!=s[n])p=t[p].ff;
if(!t[p].son[c]){
int v=++tot,k=t[p].ff;
t[v].len=t[p].len+2;
while(s[n-t[k].len-1]!=s[n])k=t[k].ff;
t[v].ff=t[k].son[c];
t[p].son[c]=v;
}
last=t[p].son[c];
}
}mm;
int main(){
scanf("%s",s+1);
int len=strlen(s+1);
sam.init();
for(int i=1;s[i];i++){
sam.extend(s[i]-'a');
}
sam.last=0;
for(int i=len;i;i--){
sam.extend(s[i]-'a');
}
ll ans=0;
for(int i=1;i<sam.sz;i++){
ans+=sam.len[i]-sam.len[sam.link[i]];
}
mm.init();
for(int i=1;i<=len;i++){
mm.extend(s[i]-'a',i);
}
ll pp=mm.tot-1;
cout<<(ans+pp)/2<<endl;
return 0;
}