Noi2016 D1 T1 优秀的拆分 90做法

来源:互联网 发布:支付宝怎么和淘宝绑定 编辑:程序博客网 时间:2024/06/05 16:08

欢迎访问博客 oi.self-jqe.win

题目大意:

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

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

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

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

做法:

我们来考虑,我们可以通过hash值判定来O1的比较两个子串是否相等,那我们可以立马想到一n^3的做法,不断的去找一个点来枚举并判断,这可以过80分,那么我们可以做一些小的改进,我们用cnt[i]表示字符串第[i,n]位能构成几种AA形式的方案。这个cnt我们可以在平方级别内来预处理出来。然后我们去枚举一个位置,暴力去找他前面的部分能构成几个AA的形式,然后与cnt[i]相乘并加入ans即可。

Ac代码

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef long long ll;ll mo1 = 951413,mo2 = 980321,jz = 30;int T,lenn;ll ans = 0;ll jl1[31000],jl2[31000],cnt[31000],ijz[31000][2];char s[31000];void hash_init(){for (int i = 1;i <= lenn;i++){jl1[i] = (jl1[i - 1] + (s[i] - 'a' + 1) * ijz[i][0]) % mo1;jl2[i] = (jl2[i - 1] + (s[i] - 'a' + 1) * ijz[i][1]) % mo2;}}bool check(int l1,int r1,int l2,int r2){ if ((r1 - l1) != (r2 - l2)) return 0;//printf("%d %d %d %d %lld %lld\n",l1,r1,l2,r2,((jl1[r1] - jl1[l1 - 1]) * ijz[l2 - l1 + 1][0]) % mo1,(jl1[r2] - jl1[l2 - 1]) % mo1);int a1 = ((jl1[r1] - jl1[l1 - 1]) * ijz[l2 - l1 + 1][0]) % mo1;int a2 = (jl1[r2] - jl1[l2 - 1]) % mo1;int b1 = ((jl2[r1] - jl2[l1 - 1]) * ijz[l2 - l1 + 1][1]) % mo2;int b2 = (jl2[r2] - jl2[l2 - 1]) % mo2;while (a1 < 0) a1 += mo1;while (a2 < 0) a2 += mo1;while (b1 < 0) b1 += mo2;while (b2 < 0) b2 += mo2;if (a1 != a2) return 0;if (b1 != b2) return 0;//printf("true\n");return 1;}void cnt_init(){for (int i = 1;i < lenn;i++)for (int j = 2;i + j - 1<= lenn;j += 2)if (check(i,i + (j >> 1) - 1,i + (j >> 1),i + j - 1)) cnt[i]++;}void solve(){for (int i = 1;i < lenn;i++){int tp = 0;for (int j = 2;i - j + 1 >= 1;j += 2)if (check(i - j + 1,i - j / 2,i - j / 2 + 1,i)) tp++; ans += tp * cnt[i + 1];}}int main(){scanf("%d",&T);ijz[1][0] = ijz[1][1] = 1;for (int i = 2;i <= 30000;i++){ijz[i][0] = ijz[i - 1][0] * jz % mo1;ijz[i][1] = ijz[i - 1][1] * jz % mo2;}for (int mi = 1;mi <= T;mi++){ans = 0;memset(cnt,0,sizeof(cnt));memset(jl1,0,sizeof(jl1));memset(jl2,0,sizeof(jl2));scanf("%s",s + 1);lenn = strlen(s + 1);hash_init();cnt_init();solve();printf("%lld\n",ans);int a,b,c,d;}return 0;}
0 0