P3900 [湖南集训]图样图森破

链接

分析:

  感觉像个暴力。

  可以枚举回文串的回文中心,即枚举一个串,枚举一个串的位置作为回文中心,然后求出这个串内的回文串的长度。

  此时如果回文串两端都没有到这个串的端点,那么以这个点作为回文中心的长度就直接算出来了。

  如果回文串的长度刚好是这个串的长度,那么INF。

  如果回文串一侧到了端点,那么枚举所有串,看看能否加到另一侧,来构成回文串。此过程记忆化搜索即可。

  复杂度$O(nL \log nL)$

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
int s[N], st[N], en[N], rnk[N], ht[N], sa[N], f[][N], Log[N], t1[N], t2[N], c[N], bel[N], dp[N][];
bool vis[N][];
char tmp[N];
int n, m; void getsa() {
int *x = t1, *y = t2, m = , i;
for (i = ; i <= m; ++i) c[i] = ;
for (i = ; i <= n; ++i) x[i] = s[i], c[x[i]] ++;
for (i = ; i <= m; ++i) c[i] += c[i - ];
for (i = n; i >= ; --i) sa[c[x[i]] --] = i;
for (int k = ; k <= n; k <<= ) {
int p = ;
for (i = n - k + ; i <= n; ++i) y[++p] = i;
for (i = ; i <= n; ++i) if (sa[i] > k) y[++p] = sa[i] - k;
for (i = ; i <= m; ++i) c[i] = ;
for (i = ; i <= n; ++i) c[x[y[i]]] ++;
for (i = ; i <= m; ++i) c[i] += c[i - ];
for (i = n; i >= ; --i) sa[c[x[y[i]]] --] = y[i];
swap(x, y);
p = ;
x[sa[]] = ;
for (i = ; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i - ]] && y[sa[i] + k] == y[sa[i - ] + k]) ? p - : p ++;
if (p > n) break;
m = p;
}
for (int i = ; i <= n; ++i) rnk[sa[i]] = i;
int k = ;
ht[] = ;
for (int i = ; i <= n; ++i) {
if (rnk[i] == ) continue;
if (k) k --;
int j = sa[rnk[i] - ];
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k ++;
ht[rnk[i]] = k;
}
Log[] = -;
for (int i = ; i <= n; ++i) Log[i] = Log[i >> ] + ;
for (int i = ; i <= n; ++i) f[][i] = ht[i];
for (int j = ; j <= Log[n]; ++j)
for (int i = ; i + ( << j) - <= n; ++i)
f[j][i] = min(f[j - ][i], f[j - ][i + ( << (j - ))]);
}
int query(int l,int r) {
if (l == r) return 1e9;
l = rnk[l], r = rnk[r];
if (l > r) swap(l, r);
l ++;
int k = Log[r - l + ];
return min(f[k][l], f[k][r - ( << k) + ]);
}
int getlcp(int x,int y) {
return min(query(x, n - y + ), min(en[bel[x]] - x + , y - st[bel[y]] + ));
}
void End() {
puts("Infinity"); exit();
}
int dfs(int x,int t) {
if (vis[x][t]) End();
if (dp[x][t]) return dp[x][t];
vis[x][t] = ;
if (!t) {
for (int i = ; i <= m; ++i) {
int k = getlcp(x, en[i]), l = en[i] - k + , r = x + k - ;
if (r != en[bel[x]] && l != st[i]) dp[x][t] = max(dp[x][t], k * );
else if (r == en[bel[x]] && l == st[i]) End();
else if (r == en[bel[x]]) dp[x][t] = max(dp[x][t], k * + dfs(l - , ));
else dp[x][t] = max(dp[x][t], k * + dfs(r + , ));
}
}
else {
for (int i = ; i <= m; ++i) {
int k = getlcp(st[i], x), l = x - k + , r = st[i] + k - ;
if (l != st[bel[x]] && r != en[i]) dp[x][t] = max(dp[x][t], k * );
else if (l == st[bel[x]] && r == en[i]) End();
else if (l == st[bel[x]]) dp[x][t] = max(dp[x][t], k * + dfs(r + , ));
else dp[x][t] = max(dp[x][t], k * + dfs(l - , ));
}
}
vis[x][t] = ;
return dp[x][t];
}
int main() {
m = read();
for (int i = ; i <= m; ++i) {
scanf("%s", tmp + );
int len = strlen(tmp + );
st[i] = n + ;
for (int j = ; j <= len; ++j) s[++n] = tmp[j] - 'a' + , bel[n] = i;
en[i] = n;
}
for (int i = ; i <= n; ++i) s[i + n] = s[n - i + ];
n <<= ;
getsa();
int ans = ;
for (int i = ; i <= m; ++i)
ans = max(ans, max(dfs(st[i], ), dfs(en[i], )));
for (int i = ; i <= m; ++i) {
for (int j = st[i]; j <= en[i]; ++j) {
int k = getlcp(j, j), l = j - k + , r = j + k - ;
if (l != st[i] && r != en[i]) ans = max(ans, k * - );
else if (l == st[i] && r == en[i]) End();
else if (l == st[i]) ans = max(ans, k * - + dfs(r + , ));
else ans = max(ans, k * - + dfs(l - , ));
}
for (int j = st[i]; j < en[i]; ++j) {
int k = getlcp(j + , j), l = j - k + , r = j + k; // r = j + 1 + k - 1 !!!
if (l != st[i] && r != en[i]) ans = max(ans, k * );
else if (l == st[i] && r == en[i]) End();
else if (l == st[i]) ans = max(ans, k * + dfs(r + , ));
else ans = max(ans, k * + dfs(l - , ));
}
}
cout << ans;
return ;
}

P3900 [湖南集训]图样图森破的更多相关文章

  1. BZOJ3654 : 图样图森破

    考虑枚举回文中心,然后向两边扩展,当匹配到当前串的边界的时候,枚举下一个串接上. 这个过程可以通过记忆化搜索来完成,设: $f[i][0]$表示对于$i$这个位置,$[i,串结尾]$等待匹配的最长回文 ...

  2. Bzoj 3654 图样图森波 题解

    3654: 图样图森破 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 123  Solved: 66[Submit][Status][Discuss] ...

  3. 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生

    题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...

  4. bzoj 3653 [湖南集训]谈笑风生

    题目描述 设 T 为一棵有根树,我们做如下的定义: • 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称"a 比 b 不知道高明到哪里去了". • 设 a ...

  5. luogu P3899 [湖南集训]谈笑风生

    传送门 nmyzd,mgdhls,bnmbzdgdnlql,a,wgttxfs 对于一个点\(a\),点\(b\)只有可能是他的祖先或者在\(a\)子树里 如果点\(b\)是\(a\)祖先,那么答案为 ...

  6. 洛谷P3899 [湖南集训]谈笑风生(线段树合并)

    题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...

  7. P3899 [湖南集训]谈笑风生

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3653 https://www.luogu.org/problemnew/show/P38 ...

  8. LG3898 [湖南集训]大新闻

    题意 题目描述 **记者弄了个大新闻,这个新闻是一个在 [0,n) 内等概率随机选择的整数,记其为 x.为了尽可能消除这个大新闻对公众造成的不良印象,我们需要在 [0,n)内找到某一个整数 y,使得 ...

  9. 【洛谷 P3899】 [湖南集训]谈笑风生 (主席树)

    题目链接 容易发现\(a,b,c\)肯定是在一条直链上的. 定义\(size(u)\)表示以\(u\)为根的子树大小(不包括\(u\)) 分两种情况, 1.\(b\)是\(a\)的祖先,对答案的贡献是 ...

随机推荐

  1. Linxu系统修改文件描述符

    修改系统文件描述符 文件描述符:无符号整数(0-65535),进程使用它来标示打开的文件    /etc/security/limits.conf:可以修改CPU,堆栈,   1.查看最大的标示符 u ...

  2. windows实现MySQL主从复制

    MySQL的主从复制是通过binlog日志来实现的,主从复制中的“主”指的是MySQL主服务器上的数据库,“从”指的是MySQL从服务器上的数据库,且这种复制是基于数据库级别的,为此从服务器中的数据库 ...

  3. 铁乐学python_day18-19_面向对象编程1

    以下笔记绝大部分(百分之80或以上)摘自我的授课老师之一:老男孩教育中的景老师. 她上课讲的知识点由浅入深,引人入胜,听她的课完全不会感觉到困阿,而且不知不觉中就感觉掌握了. 她的博客是: http: ...

  4. 铁乐学Python_day07_集合and浅谈深浅copy

    1.[List补充] 在循环一个列表时,最好不要使用元素和索引进行删除操作,一旦删除,索引会随之改变,容易出错. 如果想不出错,可以采用倒着删除的方法,因为倒着删除进行的话,只是后面元素的位置发生了变 ...

  5. 有效集 matlab代码

    %有效集 function activeset H=[2 -1; -1 4]; c=[-1 -10]'; Ae=[ ]; be=[ ]; Ai=[-3 -2; 1 0; 0 1]; bi=[-6 0 ...

  6. pathlib

    导入Path类 from pathlib import Path 创建Path对象 p = Path('C:\Windows\System32') # 用C:\Windows\System32创建Pa ...

  7. print(函数.__closure__) 来判断是不是闭包, 返回cell , 是闭包, 返回None 则不是闭包

    print(函数.__closure__) 来判断是不是闭包,  返回cell , 是闭包,       None 则不是闭包

  8. Ubuntu 配置Mysql远程连接

    首先安装mysql.mysqlclient sudo apt-get install mysql-server mysql-clientsudo apt-get install libmysqlcli ...

  9. Jmeter入门3 http请求—content-type与参数

    本文讲三种content-type以及在Jmeter中对应的参数输入方式 第一部分:目前工作中涉及到的content-type 有三种: content-type:在Request Headers里, ...

  10. 记一次webservice的超时时间设置

    一次项目组中需要控制超时时间,前期习惯用CXF实现,熟悉的才是最好的.所以这次依然想用CXF实现. 实现的方式代码如下: static{ String fvpWebserviceUrl = Prope ...