记录编号 |
408555 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[NOI 2016]优秀的拆分 |
最终得分 |
100 |
用户昵称 |
rpCardinal |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.310 s |
提交时间 |
2017-05-24 21:52:14 |
内存使用 |
33.28 MiB |
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 30000
#define LOG4N 17
using namespace std;
#ifdef _WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
int n,l2[4*MAXN+10],f[MAXN+10],g[MAXN+10];
char s[MAXN+10];
struct SuffixTree {
int ch[2*MAXN+10][26],f[2*MAXN+10],a[2*MAXN+10],b[MAXN+10],n,m,last,u[2*MAXN+10],v[2*MAXN+10],p[2*MAXN+10],me,idx,e[4*MAXN+10],pos[2*MAXN+10],mi[LOG4N+1][4*MAXN+10];
SuffixTree() {memset(ch,-1,sizeof(ch));}
void clear() {
memset(ch,-1,sizeof(ch[0])*(m+1));
m=last=n=0; f[0]=-1;
}
void addChar(int k) {
int p=last,np=++m; a[np]=a[p]+1; last=np; b[++n]=np;
while (p!=-1&&ch[p][k]==-1) {ch[p][k]=np; p=f[p];}
if (p==-1) f[np]=0;
else {
int q=ch[p][k];
if (a[q]==a[p]+1) f[np]=q;
else {
int nq=++m; a[nq]=a[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
f[nq]=f[q]; f[q]=nq; f[np]=nq;
while (p!=-1&&ch[p][k]==q) {ch[p][k]=nq; p=f[p];}
}
}
}
void addEdge(int x,int y) {
++me; v[me]=y; p[me]=u[x]; u[x]=me;
}
void dfs(int x) {
e[++idx]=x; pos[x]=idx;
for (int i=u[x];i;i=p[i]) {
dfs(v[i]); e[++idx]=x;
}
}
void buildTree() {
memset(u,0,sizeof(int)*(m+1)); me=0;
for (int i=1;i<=m;++i) addEdge(f[i],i);
idx=0; dfs(0);
for (int i=1;i<=idx;++i) mi[0][i]=a[e[i]];
for (int j=0;j<LOG4N;++j)
for (int i=1;i<=idx;++i)
mi[j+1][i]=min(mi[j][i],mi[j][i+(1<<j)]);
l2[0]=0; for (int i=1;i<=idx;++i) l2[i]=l2[i-1]+(i>>l2[i-1]>>1);
}
int lcp(int x,int y) {
x=pos[b[x]]; y=pos[b[y]];
if (x>y) swap(x,y); int d=l2[y-x];
return min(mi[d][x],mi[d][y-(1<<d)+1]);
}
}T1,T2;
int main() {
freopen("excellent.in","r",stdin);
freopen("excellent.out","w",stdout);
int T; scanf("%d",&T);
while (T--) {
scanf("%s",s+1); n=strlen(s+1);
T1.clear(); for (int i=1;i<=n;++i) T1.addChar(s[i]-'a');
T1.buildTree();
T2.clear(); for (int i=n;i;--i) T2.addChar(s[i]-'a');
T2.buildTree();
memset(f,0,sizeof(int)*(n+2));
memset(g,0,sizeof(int)*(n+2));
for (int d=1;d+d<=n;++d)
for (int i=d;i+d<=n;i+=d) {
int x=min(d,T1.lcp(i,i+d)),y=min(d-1,T2.lcp(n-i,n-i-d));
if (x+y>=d) {
++f[i+d-x+d]; --f[i+d+y+1];
++g[i+1+y-d]; --g[i-x];
}
}
for (int i=1;i<=n;++i) f[i]+=f[i-1];
for (int i=n;i;--i) g[i]+=g[i+1];
long long ans=0;
for (int i=1;i<=n;++i) ans+=1ll*f[i]*g[i+1];
printf(lld "\n",ans);
}
fclose(stdin); fclose(stdout);
return 0;
}