来自F allDream的博客,未经允许,请勿转载,谢谢。


如果一个字符串可以被拆分为 AABB 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的。

例如,对于字符串 aabaabaa,如果令 A=aab,B=a,我们就找到了这个字符串拆分成 AABB的一种方式。

一个字符串可能没有优秀的拆分,也可能存在不止一种优秀的拆分。比如我们令 A=a,B=baa,也可以用 AABB表示出上述字符串;但是,字符串 abaabaa 就没有优秀的拆分。

现在给出一个长度为 n的字符串 S,我们需要求出,在它所有子串的所有拆分方式中,优秀拆分的总个数。这里的子串是指字符串中连续的一段。

以下事项需要注意:

1.出现在不同位置的相同子串,我们认为是不同的子串,它们的优秀拆分均会被记入答案。

2.在一个拆分中,允许出现 A=B。例如 cccc 存在拆分 A=B=c。

3.字符串本身也是它的一个子串

你需要计算一个字符串的所有子串的优秀的拆分的个数之和

T(T<=10)组数据,n<=30000

这道题n^2暴力95分..

正解的话反正我是想不到...

如果知道以每个点为左/右端点构成AA的方案数,就可以计算答案

考虑求出正着反着各求出后缀数组之后,枚举长度L,然后每段长度是L把这个字符串分段

每次枚举两个端点i,j(i和j都是L的倍数,j=i+L),并且计算左端点在[i-L+1,i]内的答案。

所以求一下点i,j正着的lcp,反着的lcp,也就是从点i开始能向左右扩展到哪里,如果能扩展到的长度大等于L,那么就有答案

假设倒着时候的lcp是a,正着的是b,也就是[i-a+1,i]和[j-a+1,j]相同(显然a>0),b同理,那么有答案的左端点区间是[i-a+1,i-a+1 + (a+b-1-L) -1] 差分即可。

复杂度Tnlogn

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define ll long long
  5. #define MN 30000
  6. #define MD 15
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x = ; char ch = getchar();
  11. while(ch < '' || ch > '') ch = getchar();
  12. while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
  13. return x;
  14. }
  15.  
  16. int n,k,lt[MN+],rt[MN+],v[MN+],Log[MN+];ll ans;
  17. char st[MN*+],st2[MN*+];
  18.  
  19. void CalSa(int*SA,int*RK,int*sa,int*rk)
  20. {
  21. for(int i=;i<=n;++i) v[rk[sa[i]]]=i;
  22. for(int i=n;i;--i)
  23. if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;
  24. for(int i=n-k+;i<=n;++i) SA[v[rk[i]]--]=i;
  25. for(int i=;i<=n;++i)
  26. RK[SA[i]]=RK[SA[i-]]+(rk[SA[i]]!=rk[SA[i-]]||rk[SA[i]+k]!=rk[SA[i-]+k]);
  27. }
  28.  
  29. void GetH(int*H,int*sa,int*rk,char*s)
  30. {
  31. for(int i=,k=;i<=n;H[rk[i++]-]=k,k?--k:) if(rk[i]>)
  32. for(int j=sa[rk[i]-];s[j+k]==s[i+k];++k);
  33.  
  34. }
  35.  
  36. struct SuffixArray
  37. {
  38. int p,q,sa[][MN+],rk[][MN+],f[MD+][MN+],F[MD+][MN+],fa[MD+][MN+],Fa[MD+][MN+];
  39. inline void Clear(){p=;q=;
  40. memset(rk,,sizeof(rk));
  41. memset(sa,,sizeof(sa));
  42. }
  43. void Build(char *s)
  44. {
  45. memset(v,,sizeof(int)*);
  46. for(int i=;i<=n;++i)++v[s[i]-'a'];
  47. for(int i=;i<;++i) v[i]+=v[i-];
  48. for(int i=;i<=n;++i) sa[q][v[s[i]-'a']--]=i;
  49. for(int i=;i<=n;++i)
  50. rk[q][sa[q][i]]=rk[q][sa[q][i-]]+(s[sa[q][i]]!=s[sa[q][i-]]);
  51. for(k=;k<n;k<<=)
  52. {
  53. CalSa(sa[p],rk[p],sa[q],rk[q]);
  54. swap(p,q);
  55. }
  56. }
  57. void BuildHeight(char *s)
  58. {
  59. GetH(f[],sa[q],rk[q],s);
  60. for(int i=;i<=n;++i) F[][i]=f[][i-];
  61. for(int i=;i<=MD;++i) F[i][]=f[i][]=f[i][n]=F[i][]=MN;
  62. for(int i=;i<n;++i) fa[][i]=i+,Fa[][i+]=i;
  63. for(int i=;i<=MD;++i)
  64. for(int j=;j<=n;++j)
  65. fa[i][j]=fa[i-][fa[i-][j]],
  66. Fa[i][j]=Fa[i-][Fa[i-][j]],
  67. f[i][j]=min(f[i-][j],f[i-][fa[i-][j]]),
  68. F[i][j]=min(F[i-][j],F[i-][Fa[i-][j]]);
  69. }
  70. int query(int i,int j)
  71. {
  72. i=rk[q][i],j=rk[q][j];
  73. if(i>j) swap(i,j);
  74. int L=Log[j-i];
  75. return min(f[L][i],F[L][j]);
  76. }
  77. }P,S;
  78.  
  79. int main()
  80. {
  81. Log[]=-;
  82. for(int i=;i<=MN;++i) Log[i]=Log[i>>]+;
  83. for(int T=read();T;--T)
  84. {
  85. scanf("%s",st+);n=strlen(st+);
  86. for(int i=;i<=n;++i) st2[i]=st[n-i+];
  87. P.Clear();S.Clear();ans=;
  88. P.Build(st);S.Build(st2);
  89. P.BuildHeight(st);
  90. S.BuildHeight(st2);
  91. memset(lt,,sizeof(lt));
  92. memset(rt,,sizeof(rt));
  93. for(int L=;L<=n;++L)
  94. for(int i=L,j=i+L;j<=n;i=j,j+=L)
  95. {
  96. int a=P.query(i,j),b=S.query(n-j+,n-i+);
  97. if(min(a,L)+min(b,L)->=L)
  98. {
  99. int len=min(a,L)+min(b,L)--L;
  100. ++lt[i-min(b,L)+],--lt[i-min(b,L)+len+],
  101. ++rt[j-min(b,L)+L],--rt[j-min(b,L)+L+len+];
  102. }
  103. }
  104. for(int i=;i<=n;++i) lt[i]+=lt[i-],rt[i]+=rt[i-];
  105. for(int i=;i<n;++i) ans+=1LL*rt[i]*lt[i+];
  106. printf("%lld\n",ans);
  107. }
  108. return ;
  109. }

[Noi2016]优秀的拆分的更多相关文章

  1. [NOI2016]优秀的拆分&&BZOJ2119股市的预测

    [NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...

  2. luogu1117 [NOI2016]优秀的拆分

    luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...

  3. 【BZOJ4560】[NOI2016]优秀的拆分

    [BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...

  4. [UOJ#219][BZOJ4650][Noi2016]优秀的拆分

    [UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...

  5. [NOI2016]优秀的拆分(SA数组)

    [NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...

  6. 题解-NOI2016 优秀的拆分

    NOI2016 优秀的拆分 \(T\) 组测试数据.求字符串 \(s\) 的所有子串拆成 \(AABB\) 形式的方案总和. 数据范围:\(1\le T\le 10\),\(1\le n\le 3\c ...

  7. [NOI2016]优秀的拆分 后缀数组

    题面:洛谷 题解: 因为对于原串的每个长度不一定等于len的拆分而言,如果合法,它将只会被对应的子串统计贡献. 所以子串这个限制相当于是没有的. 所以我们只需要对于每个位置i求出f[i]表示以i为开头 ...

  8. [BZOJ]4650: [Noi2016]优秀的拆分

    Time Limit: 30 Sec  Memory Limit: 512 MB Description 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串, ...

  9. 【刷题】BZOJ 4650 [Noi2016]优秀的拆分

    Description 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串,则我们称该字符串的这种拆分是优秀的.例如,对于字符串 aabaabaa,如果令 A ...

随机推荐

  1. php实现单,双向链表,环形链表解决约瑟夫问题

    传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季  http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求 ...

  2. CentOS 7 GUI图形界面安装

    在此之前先获取root权限,进行以下命令: 1. 在命令行下输入下面的命令来安装Gnome包: yum groupinstall "GNOME Desktop" "Gra ...

  3. Linq 集合操作符 Except,Intersect,Union

    IList<string> s1 = new List<string>() { "One", "Two", "Three&qu ...

  4. JVM学习记录

    本博客是为了自己学习JVM而建立,只记录一些自己学习的经过. 最近在看<深入理解Java虚拟机>这本书,里面的内容,很是乏味,因为看不懂所以就会觉得很枯燥,觉得很枯燥看着看着就犯困,然后就 ...

  5. jq 滚轮监听事件

    windowAddMouseWheel(); function windowAddMouseWheel() { var i = 0; var scrollFunc = function (e) { e ...

  6. iot会议纪要 20180105

    1.需求概述设备 <-->物接入 <--> 云端认证授权协议解析主题 端点endpoint(地址)->设备thing(用户)->身份principal(密码)-&g ...

  7. html5shiv.js和respond.min.js的作用

    html5shiv:解决ie9以下浏览器对html5新增标签的不识别,并导致CSS不起作用的问题. respond.min:让不支持css3 Media Query的浏览器包括IE6-IE8等其他浏览 ...

  8. RxJava系列1(简介)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  9. tar命令-vi编辑器-磁盘分区及格式化-软链接及硬链接文件

    一.tar命令 1.将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) [root@localhost  /] #  cat  /etc/passwd  /etc/group ...

  10. Http协议消息报头

    哎.不知道怎么写Http协议... 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议. HTTP基于TCP/IP通信协议来传递数据 ...