Luogu P1117 [NOI2016]优秀的拆分
题目链接 \(Click\) \(Here\)
这题质量不错,就是暴力分有点足\(hhhhhhhh\),整整有\(95\)分。
(搞得我写完暴力都不想写正解直接理解思路之后就直接水过去了\(QwQ\))
(啊好啦好啦水过去是我的锅啦,我自己出来挨打还不行嘛\(QAQ\))
其实就是把\(AABB\)换成求\(AA\)然后组合在一块,最后的部分需要推一个奇妙的性质,这里我也不好叙述,详情请见这个大佬的博客。至于求\(AA\)的方法可以考虑使用后缀数组+\(RMQ\)实现\(O(1)\)匹配。
(别跟我提哈希听着就来气\(TwT\),为什么还可以用\(Hash\)水啊喂!)
\(95pts:\)
#include <bits/stdc++.h>
using namespace std;
const int N = 4010;
char s[N];
int n, m, T;
int sa[N], tp[N], rk[N], _rk[N], bin[N], height[N];
void get_height () {
int k = 0;
for (int i = 1; i <= n; ++i) {
if (k != 0) --k;
int j = sa[rk[i] - 1];
while (s[i + k - 1] == s[j + k - 1]) ++k;
height[rk[i]] = k;
}
}
void base_sort () {
for (int i = 1; i <= m; ++i) bin[i] = 0;
for (int i = 1; i <= n; ++i) bin[rk[tp[i]]]++;
for (int i = 1; i <= m; ++i) bin[i] += bin[i - 1];
for (int i = n; i >= 1; --i) sa[bin[rk[tp[i]]]--] = tp[i];
}
void suffix_sort () {
m = 255;
for (int i = 1; i <= n; ++i) {
tp[i] = i, rk[i] = s[i - 1];
}
base_sort ();
for (int w = 1; w <= n; w <<= 1) {
int cnt = 0;
for (int i = n - w + 1; i <= n; ++i) {
tp[++cnt] = i;
}
for (int i = 1; i <= n; ++i) {
if (sa[i] > w) {
tp[++cnt] = sa[i] - w;
}
}
base_sort ();
memcpy (_rk, rk, sizeof (rk));
rk[sa[1]] = cnt = 1;
for (int i = 2; i <= n; ++i) {
rk[sa[i]] = (_rk[sa[i]] == _rk[sa[i - 1]]) && (_rk[sa[i] + w] == _rk[sa[i - 1] + w]) ? cnt : ++cnt;
}
if (cnt == n) break;
m = cnt;
}
}
int a[N], b[N], st[N][25];
void get_STlist () {
memset (st, 0, sizeof (st));
for (int i = 1; i <= n; ++i) {
st[i][0] = height[i];
}
int mx = log2 (n);
for (int i = 1; i <= mx; ++i) {
for (int j = 1; j + (1 << i) - 1 <= n; ++j) {
st[j][i] = min (st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
}
}
}
int lcp (int x, int y) {
if (x > y) swap (x, y); ++x;
if (x > y) return 0;
int mx = log2 (y - x + 1);
return min (st[x][mx], st[y - (1 << mx) + 1][mx]);
}
void Initialize () {
memset (a, 0, sizeof (a));
memset (b, 0, sizeof (b));
memset (s, 0, sizeof (s));
memset (sa, 0, sizeof (sa));
memset (tp, 0, sizeof (tp));
memset (rk, 0, sizeof (rk));
memset (height, 0, sizeof (height));
scanf ("%s", s);
n = strlen (s);
}
int main () {
cin >> T;
while (T--) {
Initialize ();
suffix_sort ();
get_height ();
get_STlist ();
for (int i = 0; i < n; ++i) { //枚举每一个后缀
for (int l = 1; i + l * 2 - 1 < n; ++l) {
// printf ("lcp (rk[%d] = %d, rk[%d] = %d) = %d\n", i, rk[i], i + l, rk[i + l], lcp (rk[i], rk[i + l]))
if (lcp (rk[i + 1], rk[i + l + 1]) >= l) {
a[i + l * 2 - 1]++, b[i]++;
}
}
}
long long ans = 0;
for (int i = 0; i < n; ++i) {
ans += a[i] * b[i + 1];
}
cout << ans << endl;
}
}
\(100pts\)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define Set(a, v) memset(a, v, sizeof(a))
#define For(i, a, b) for(int i = (a); i <= (int)(b); i++)
#define Forr(i, a, b) for(int i = (a); i >= (int)(b); i--)
#define LOG (15+5)
#define MAXN (30000+5)
int n, c[MAXN], c1[MAXN], c2[MAXN], Log[MAXN];
struct SuffixArray{
char s[MAXN];
int sa[MAXN], h[MAXN][LOG], rank[MAXN];
void init(){
Set(c1, 0); Set(c2, 0);
}
void buildsa(int m='z'){
int *x = c1, *y = c2;
For(i, 1, m) c[i] = 0;
For(i, 1, n) c[x[i]=s[i]]++;
For(i, 1, m) c[i] += c[i-1];
Forr(i, n, 1) sa[c[x[i]]--] = i;
int p;
for(int k = 1; k <= n; k <<= 1){
p = 0;
For(i, n-k+1, n) y[++p] = i;
For(i, 1, n) if(sa[i] > k) y[++p] = sa[i]-k;
For(i, 1, m) c[i] = 0;
For(i, 1, n) c[x[y[i]]]++;
For(i, 1, m) c[i] += c[i-1];
Forr(i, n, 1) sa[c[x[y[i]]]--] = y[i];
swap(x, y);
p = x[sa[1]] = 1;
For(i, 2, n) x[sa[i]] = (y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])? p: ++p;
if(p >= n) break;
m = p;
}
}
void getheight(){
For(i, 1, n) rank[sa[i]] = i;
int k = 0, j;
For(i, 1, n){
if(k) k--;
j = sa[rank[i]+1];
if(rank[i] == n) continue;
while(s[i+k] == s[j+k]) k++;
h[rank[i]][0] = k;
}
For(j, 1, 15) For(i, 1, n){
if(i+(1<<(j-1)) > n) break;
h[i][j] = min(h[i][j-1], h[i+(1<<(j-1))][j-1]);
}
}
int LCP(int x, int y){
x = rank[x]; y = rank[y];
if(x > y) swap(x, y);
int k = Log[y-x];
return min(h[x][k], h[y-(1<<k)][k]);
}
}A, B;
int st[MAXN], en[MAXN];
int main(){
For(i, 2, MAXN-1) Log[i] = Log[i>>1]+1;
int T;
scanf("%d", &T);
while(T--){
A.init(); B.init();
Set(st, 0); Set(en, 0);
scanf("%s", A.s+1);
n = strlen(A.s+1);
For(i, 1, n) B.s[i] = A.s[n-i+1];
A.buildsa(); A.getheight();
B.buildsa(); B.getheight();
int j, x, y, t;
For(L, 1, n/2){
for(int i=L, j=i+L; j <= n; i+=L,j+=L){
x = min(A.LCP(i,j), L), y = min(B.LCP(n-(i-1)+1, n-(j-1)+1), L-1);
t = x+y-L+1;
if(x+y >= L){
st[i-y]++; st[i-y+t]--;
en[j+x-t]++; en[j+x]--;
}
}
}
For(i, 1, n) st[i]+=st[i-1], en[i]+=en[i-1];
LL ans = 0;
For(i, 1, n) ans += 1LL*en[i]*st[i+1];
printf("%lld\n", ans);
}
return 0;
}
Luogu P1117 [NOI2016]优秀的拆分的更多相关文章
- UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)
连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题目链接: (luogu)https://www.luogu.org/problemnew/show/P1117 ( ...
- P1117 [NOI2016]优秀的拆分
$ \color{#0066ff}{ 题目描述 }$ 如果一个字符串可以被拆分为\(AABB\)的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串\(aab ...
- 并不对劲的bzoj4650:loj2083:uoj219:p1117:[NOI2016]优秀的拆分
题目大意 "优秀的拆分"指将一个字符串拆分成AABB的形式 十次询问,每次给出一个字符串S(\(|S|\leq3*10^4\)),求它的所有子串的优秀的拆分的方案数之和 题解 此题 ...
- luogu1117 [NOI2016]优秀的拆分
luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- 【BZOJ4560】[NOI2016]优秀的拆分
[BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- [NOI2016]优秀的拆分(SA数组)
[NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...
- 题解-NOI2016 优秀的拆分
NOI2016 优秀的拆分 \(T\) 组测试数据.求字符串 \(s\) 的所有子串拆成 \(AABB\) 形式的方案总和. 数据范围:\(1\le T\le 10\),\(1\le n\le 3\c ...
随机推荐
- Spring Boot 构建电商基础秒杀项目 (七) 自动校验
SpringBoot构建电商基础秒杀项目 学习笔记 修改 UserModel 添加注解 public class UserModel { private Integer id; @NotBlank(m ...
- 微软已发布 Windows 10 Timeline 功能的官方 Chrome 插件
微软已发布 Windows 10 Timeline 功能的官方 Chrome 插件,这个插件名为 Web Activities,功能是跨 Windows 10 和 Microsoft Launcher ...
- 炎黄流程中改流程节点颜色的js
- BZOJ2038[2009国家集训队]小Z的袜子(hose)——莫队
题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号 ...
- PHP——判断数组中是否有重复值并找出重复值
可以用来测试需要唯一凭据号码的,是否有重复值,不过一般直接使用uuid了,简单粗暴就解决问题,这个就简单的测试生成的数据是否有重复值吧 <?php /* * @Author: wyy * @Da ...
- Hibernate 注解映射
工作中遇到hibernate映射的一些问题,这里总结一下 (特别是测试时,许多数据并不能有效关联.所以@NotFound 很重要) 一,假设有2张表user,company 我们知道,一个用户属于一个 ...
- SpringBoot整合ssm
1.创建工程 使用idea可以快速创建SpringBoot的工程 这里选择常用的类库,SpringBoot将各种框架类库都进行了封装,可以减少pom文件中的引用配置: 比如Spring和Mybatis ...
- Windows10 + Visual Studio 2017环境为C++工程安装使用ZMQ
因为需要用 C++ 实现联机对战的功能,但是不想直接用 winsock ,因此选了ZMQ 框架(不知道合不合适).安装的过程还是挺艰辛的.但是也学到了些东西,记录一下.另外,Zmq 的作者 Piete ...
- 「SCOI2014」方伯伯运椰子 解题报告
「SCOI2014」方伯伯运椰子 可以看出是分数规划 然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的. 然后按照套路 ...
- [SCOI2007]压缩(区间dp)
神仙题,看了半天题解才看明白... 因为题目里说如果没有m,会自动默认m在最前面. 我们设计状态为dp[l][r][0/1]为在区间l到r中有没有m的最小长度. 转移:枚举我们要压缩的起点,dp[l] ...