P3900 [湖南集训]图样图森破
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 [湖南集训]图样图森破的更多相关文章
- BZOJ3654 : 图样图森破
考虑枚举回文中心,然后向两边扩展,当匹配到当前串的边界的时候,枚举下一个串接上. 这个过程可以通过记忆化搜索来完成,设: $f[i][0]$表示对于$i$这个位置,$[i,串结尾]$等待匹配的最长回文 ...
- Bzoj 3654 图样图森波 题解
3654: 图样图森破 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 123 Solved: 66[Submit][Status][Discuss] ...
- 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生
题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...
- bzoj 3653 [湖南集训]谈笑风生
题目描述 设 T 为一棵有根树,我们做如下的定义: • 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称"a 比 b 不知道高明到哪里去了". • 设 a ...
- luogu P3899 [湖南集训]谈笑风生
传送门 nmyzd,mgdhls,bnmbzdgdnlql,a,wgttxfs 对于一个点\(a\),点\(b\)只有可能是他的祖先或者在\(a\)子树里 如果点\(b\)是\(a\)祖先,那么答案为 ...
- 洛谷P3899 [湖南集训]谈笑风生(线段树合并)
题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...
- P3899 [湖南集训]谈笑风生
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3653 https://www.luogu.org/problemnew/show/P38 ...
- LG3898 [湖南集训]大新闻
题意 题目描述 **记者弄了个大新闻,这个新闻是一个在 [0,n) 内等概率随机选择的整数,记其为 x.为了尽可能消除这个大新闻对公众造成的不良印象,我们需要在 [0,n)内找到某一个整数 y,使得 ...
- 【洛谷 P3899】 [湖南集训]谈笑风生 (主席树)
题目链接 容易发现\(a,b,c\)肯定是在一条直链上的. 定义\(size(u)\)表示以\(u\)为根的子树大小(不包括\(u\)) 分两种情况, 1.\(b\)是\(a\)的祖先,对答案的贡献是 ...
随机推荐
- [WinCE | VS2008 | Solution] VS2008 building WinCE projects taking a long time
1. Open C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.CompactFramework.Common.targets 2. Find pa ...
- 查看windows所有exe的启动参数。
在cmd中输入 wmicprocess 即可查看到所有进程的启动参数和运行参数.
- 要提高SQL查询效率where语句条件的先后次序应如何写
我们要做到不但会写SQL,还要做到写出性能优良的SQL语句. (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句 ...
- ETL探索之旅
ETL(Ectract Transform Load) 抽取-转换-加载 ETL 商业软件: Informatica IBM DataStage Microsoft SSIS Oracle ODI ...
- Windows程序设计(Charles Petzold)HELLOWIN程序实现
/*-------------------------------------------------------------- HELLOWIN.C--DisPlays "Hello, W ...
- 从 s = "我爱北京天安门" 中悟道了-----------迭代器操作print(c.__next__())的最!大!好!处!-----------------------------------------------------可以一个一个输出
s = "我爱北京天安⻔"c = s.__iter__() # 获取迭代器# print(c) # 打印迭代器的地址# print(c.__next__()) # 打印迭代器中的下 ...
- list(range())--------range创建一个list列表 遍历索引range(len()) 和 list(range())创建列表
lst = list(range(15,26)) #注,list(range())用的是小括号哦print(lst)
- CSS 鼠标样式
设置鼠标指针放在一个元素边界范围内时所用的光标形状,需要对元素的css属性cursor进行设置. cursor属性可能的值: default 默认光标(通常是一个箭头) auto 默认.浏览器设置的( ...
- 处理Account locked due to 217 failed logins的问题
处理Account locked due to 217 failed logins的问题 [root@xxx1 ~]# scp 123.txt root@IP地址:/root Account lock ...
- HashMap,LinkedHashMap和Hashtable类的深入剖析与理解
上一篇文章写了一些关于HashMap以及HashMap的线程安全问题,这篇文章再来说说Map系列中HashMap,LinkedHashMap和Hashtable三者之间的差异以及该注意的地方. Has ...