记录编号 408555 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2016]优秀的拆分 最终得分 100
用户昵称 GravatarrpCardinal 是否通过 通过
代码语言 C++ 运行时间 0.310 s
提交时间 2017-05-24 21:52:14 内存使用 33.28 MiB
显示代码纯文本
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define MAXN 30000
  5. #define LOG4N 17
  6. using namespace std;
  7.  
  8. #ifdef _WIN32
  9. #define lld "%I64d"
  10. #else
  11. #define lld "%lld"
  12. #endif
  13.  
  14. int n,l2[4*MAXN+10],f[MAXN+10],g[MAXN+10];
  15. char s[MAXN+10];
  16.  
  17. struct SuffixTree {
  18. 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];
  19. SuffixTree() {memset(ch,-1,sizeof(ch));}
  20. void clear() {
  21. memset(ch,-1,sizeof(ch[0])*(m+1));
  22. m=last=n=0; f[0]=-1;
  23. }
  24. void addChar(int k) {
  25. int p=last,np=++m; a[np]=a[p]+1; last=np; b[++n]=np;
  26. while (p!=-1&&ch[p][k]==-1) {ch[p][k]=np; p=f[p];}
  27. if (p==-1) f[np]=0;
  28. else {
  29. int q=ch[p][k];
  30. if (a[q]==a[p]+1) f[np]=q;
  31. else {
  32. int nq=++m; a[nq]=a[p]+1;
  33. memcpy(ch[nq],ch[q],sizeof(ch[nq]));
  34. f[nq]=f[q]; f[q]=nq; f[np]=nq;
  35. while (p!=-1&&ch[p][k]==q) {ch[p][k]=nq; p=f[p];}
  36. }
  37. }
  38. }
  39. void addEdge(int x,int y) {
  40. ++me; v[me]=y; p[me]=u[x]; u[x]=me;
  41. }
  42. void dfs(int x) {
  43. e[++idx]=x; pos[x]=idx;
  44. for (int i=u[x];i;i=p[i]) {
  45. dfs(v[i]); e[++idx]=x;
  46. }
  47. }
  48. void buildTree() {
  49. memset(u,0,sizeof(int)*(m+1)); me=0;
  50. for (int i=1;i<=m;++i) addEdge(f[i],i);
  51. idx=0; dfs(0);
  52. for (int i=1;i<=idx;++i) mi[0][i]=a[e[i]];
  53. for (int j=0;j<LOG4N;++j)
  54. for (int i=1;i<=idx;++i)
  55. mi[j+1][i]=min(mi[j][i],mi[j][i+(1<<j)]);
  56. l2[0]=0; for (int i=1;i<=idx;++i) l2[i]=l2[i-1]+(i>>l2[i-1]>>1);
  57. }
  58. int lcp(int x,int y) {
  59. x=pos[b[x]]; y=pos[b[y]];
  60. if (x>y) swap(x,y); int d=l2[y-x];
  61. return min(mi[d][x],mi[d][y-(1<<d)+1]);
  62. }
  63. }T1,T2;
  64.  
  65. int main() {
  66. freopen("excellent.in","r",stdin);
  67. freopen("excellent.out","w",stdout);
  68. int T; scanf("%d",&T);
  69. while (T--) {
  70. scanf("%s",s+1); n=strlen(s+1);
  71. T1.clear(); for (int i=1;i<=n;++i) T1.addChar(s[i]-'a');
  72. T1.buildTree();
  73. T2.clear(); for (int i=n;i;--i) T2.addChar(s[i]-'a');
  74. T2.buildTree();
  75. memset(f,0,sizeof(int)*(n+2));
  76. memset(g,0,sizeof(int)*(n+2));
  77. for (int d=1;d+d<=n;++d)
  78. for (int i=d;i+d<=n;i+=d) {
  79. int x=min(d,T1.lcp(i,i+d)),y=min(d-1,T2.lcp(n-i,n-i-d));
  80. if (x+y>=d) {
  81. ++f[i+d-x+d]; --f[i+d+y+1];
  82. ++g[i+1+y-d]; --g[i-x];
  83. }
  84. }
  85. for (int i=1;i<=n;++i) f[i]+=f[i-1];
  86. for (int i=n;i;--i) g[i]+=g[i+1];
  87. long long ans=0;
  88. for (int i=1;i<=n;++i) ans+=1ll*f[i]*g[i+1];
  89. printf(lld "\n",ans);
  90. }
  91. fclose(stdin); fclose(stdout);
  92. return 0;
  93. }