博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4650: [Noi2016]优秀的拆分
阅读量:4626 次
发布时间:2019-06-09

本文共 3845 字,大约阅读时间需要 12 分钟。

Description

如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串,则我们称该字符串的这种拆分是优秀的。
例如,对于字符串 aabaabaa,如果令 A=aab,B=a,我们就找到了这个字符串拆分成 AABB 的一种方式。
一个字符串可能没有优秀的拆分,也可能存在不止一种优秀的拆分。
比如我们令 A=a,B=baa,也可以用 AABB 表示出上述字符串;但是,字符串 abaabaa 就没有优秀的拆分。
现在给出一个长度为 n 的字符串 S,我们需要求出,在它所有子串的所有拆分方式中,优秀拆分的总个数。
这里的子串是指字符串中连续的一段。
以下事项需要注意:出现在不同位置的相同子串,我们认为是不同的子串,它们的优秀拆分均会被记入答案。
在一个拆分中,允许出现 A=B。例如 cccc 存在拆分 A=B=c。字符串本身也是它的一个子串。

Input

每个输入文件包含多组数据。
输入文件的第一行只有一个整数 T,表示数据的组数。
保证 1≤T≤10。
接下来 T 行,每行包含一个仅由英文小写字母构成的字符串 S,意义如题所述。

Output

输出 T 行,每行包含一个整数,表示字符串 S 所有子串的所有拆分中,总共有多少个是优秀的拆分。

Sample Input

4
aabbbb
cccccc
aabaabaabaa
bbaabaababaaba

Sample Output

3
5
4
7

HINT

我们用 S[i,j] 表示字符串 S 第 i 个字符到第 j 个字符的子串(从 1 开始计数)。
第一组数据中,共有 33 个子串存在优秀的拆分:
S[1,4]=aabb,优秀的拆分为 A=a,B=b;
S[3,6]=bbbb,优秀的拆分为 A=b,B=b;
S[1,6]=aabbbb,优秀的拆分为 A=a,B=bb。
而剩下的子串不存在优秀的拆分,所以第一组数据的答案是 3。
第二组数据中,有两类,总共 4 个子串存在优秀的拆分:
对于子串 S[1,4]=S[2,5]=S[3,6]=cccc,它们优秀的拆分相同,均为 A=c,B=c,但由于这些子串位置不同,因此要计算 3 次;
对于子串 S[1,6]=cccccc,它优秀的拆分有 2 种:A=c,B=cc 和 A=cc,B=c,它们是相同子串的不同拆分,也都要计入答案。
所以第二组数据的答案是 3+2=5
第三组数据中,S[1,8] 和 S[4,11] 各有 2 种优秀的拆分,其中 S[1
,8] 是问题描述中的例子,所以答案是 2+2=4。
第四组数据中,S[1,4],S[6,11],S[7
,12],S[2,11],S[1,8] 各有 1 种优秀的拆分,S[3,14] 有 2 种优秀的拆分,
所以答案是 5+2=7。

题解Here!
感觉有点像后缀数组。。。
没错就是后缀数组。

显然我们不用处理什么$AABB$,只需要去处理所有$AA$的形式,再去统计答案即可。

设$Left[i]$表示以$i$这个字符开头的$AA$型子串的数目。

设$Right[i]$表示以$i$这个字符结尾的$AA$型子串的数目。

则:$Ans=\sum_{i=1}^{n-1}Left[i+1]\times Right[i]$

顺序求一遍,反过来再求一遍,$Left[i],Right[i]$就可以求解了。

问题是怎么求解。

我们可以枚举找的$AA$型子串长度的一半,去判断$LCP$与$LCS$

枚举$i=k\times len,j=i+len,j<=n$

设$x=LCP(suffix(i),suffix(j)),y=LCS(prefix(i−1),prefix(j−1))$

若$x+y>=len$,那么我们就找到了$x+y−len+1$个长度为$2\times len$的$AA$型子串

差分一下,最后做一遍前缀和即可。

注:记得清空数组。。。

附代码:

#include
#include
#include
#include
#include
#define MAXN 50010using namespace std;int n;long long Left[MAXN],Right[MAXN];inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w;}struct Suffix_Array{ char str[MAXN]; int top,sa[MAXN],rk[MAXN],tax[MAXN],tp[MAXN],height[MAXN],f[MAXN][20]; void radixsort(){ for(int i=0;i<=top;i++)tax[i]=0; for(int i=1;i<=n;i++)tax[rk[i]]++; for(int i=1;i<=top;i++)tax[i]+=tax[i-1]; for(int i=n;i>=1;i--)sa[tax[rk[tp[i]]]--]=tp[i]; } void suffixsort(){ top=128; for(int i=1;i<=n;i++){ rk[i]=str[i]; tp[i]=i; } radixsort(); for(int w=1,p=0;p
<<=1){ p=0; for(int i=1;i<=w;i++)tp[++p]=n-w+i; for(int i=1;i<=n;i++)if(sa[i]>w)tp[++p]=sa[i]-w; radixsort(); swap(tp,rk); rk[sa[1]]=p=1; for(int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p; } } void getheight(){ for(int i=1,j,k=0;i<=n;i++){ if(k)k--; j=sa[rk[i]-1]; while(str[i+k]==str[j+k])k++; height[rk[i]]=k; } } void step(){ for(int i=1;i<=n;i++)f[i][0]=height[i]; for(int i=1;(1<
<=n;i++) for(int j=1;j+(1<
<=n;j++) f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]); } int query(int l,int r){ l=rk[l];r=rk[r]; if(l>r)swap(l,r); l++; int k=(int)log2(r-l+1); return min(f[l][k],f[r-(1<
>1);k++) for(int i=k,j=i+k;j<=n;i+=k,j+=k){ int x=min(k,A.query(i,j)),y=min(k-1,B.query(n-(i-1)+1,n-(j-1)+1)); if(x+y>=k){ int t=x+y-k+1; Left[i-y]++;Left[i-y+t]--; Right[j+x-t]++;Right[j+x]--; } } for(int i=1;i<=n;i++){ Left[i]+=Left[i-1]; Right[i]+=Right[i-1]; } for(int i=1;i<=n;i++)ans+=Left[i+1]*Right[i]; printf("%lld\n",ans);}void init(){ memset(Left,0,sizeof(Left)); memset(Right,0,sizeof(Right)); A.clean();B.clean(); scanf("%s",A.str+1); n=strlen(A.str+1); for(int i=1;i<=n;i++)B.str[i]=A.str[n-i+1]; A.build();B.build();}int main(){ int t=read(); while(t--){ init(); work(); } return 0;}

 

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9458910.html

你可能感兴趣的文章
H国的身份证号码(搜索)
查看>>
[luoguP2618] 数字工程(DP)
查看>>
bzoj1854: [Scoi2010]游戏
查看>>
linux 修改时区
查看>>
Android之自定义AlertDialog无法监听控件
查看>>
[Win]进程间通信——邮槽Mailslot
查看>>
第3章 模板
查看>>
Git创建本地分支并关联远程分支
查看>>
Java 访问权限控制:你真的了解 protected 关键字吗?
查看>>
八、LaTex中的表格
查看>>
MSSQLid清零
查看>>
C# using 语法说明
查看>>
Android与iOS对比
查看>>
前端常用正则表达式
查看>>
熟悉常用的Linux操作
查看>>
天平称球问题-转
查看>>
复制构造函数(拷贝构造函数)
查看>>
Android Fragment 真正的完全解析(上)
查看>>
preparedStatement平台:
查看>>
C++ RCSP智能指针简单实现与应用
查看>>