我要死了。这是我做过的最恶心的题之一。

天下第一的大毒瘤。有gay毒。

我不如熊猫好多年...


题意:给定字符串,求g[i],表示:[0, i]中满足该子串既是前缀又是后缀还不重叠的子串数。

解:题面都写了KMP,想必跟KMP有关。

然后我痛苦的思考了1天无果......

我首先想到求出nex[]和f[],f[]表示可重叠的既是前缀又是后缀的子串数。

然后想找出f[]和g[]的关系,失败。

然后想到再来一个len[]表示f[]最长的那一个的长度,还是不行...

被折磨了一天,撑不住了,在吃完饭的时候开始看题解。

发现:我们要魔改KMP,每次跳完增加之后若大于一半,就再跳...

这时你停住的地方j就是恰好比一半小的最大值。

然后如果i这里的nex为0,j显然为0,g[]显然也为0

否则j不为0,这时你把f[j - 1]加1就是g[i]

你加的1就是[0, j - 1]这个串。

然后j可以直接继承到下一个i

因为你的j和KMP里的j差不多,除了不超过一半之外都一样。

然后你i每次 + 1的时候g[]最多 + 1

这样就搞过了这个大毒瘤题....

(事实上还不是很清楚)

 #include <cstdio>
#include <cstring> typedef long long LL; const int N = , MO = 1e9 + ; int nex[N], f[N], g[N];
char s[N]; inline void solve() {
scanf("%s", s);
int n = strlen(s);
nex[] = ;
f[] = ;
for(int i = , j = ; i < n; i++) {
while(j && s[i] != s[j]) {
j = nex[j - ];
}
if(s[i] == s[j]) {
j++;
}
nex[i] = j;
if(j) {
f[i] = f[j - ] + ;
}
else {
f[i] = ;
}
} g[] = ;
LL ans = ;
for(int i = , j = ; i < n; i++) {
while(j && s[i] != s[j]) {
j = nex[j - ];
}
if(s[i] == s[j]) {
j++;
}
while( * j > (i + )) {
j = nex[j - ];
}
if(!j) {
g[i] = ;
}
else {
g[i] = f[j - ] + ;
}
ans = (ans * (g[i] + )) % MO;
}
printf("%lld\n", ans);
return;
} int main() {
int T;
scanf("%d", &T);
while(T--) {
solve();
}
return ;
}

AC代码

[update]首先有个30分暴力想必大家都会。

说一下SAM做法。你考虑一个border是什么样的,显然前缀是一条链,而后缀是该点在fail树上到根的链。于是相当于求这两个东西的交,还有个深度限制。

给前缀链标记为1,非前缀标记为0,并统计到根路径的点权和。这样,我们只要找到每个点在fail树上满足限制的最深的点,就能知道答案了。

考虑到每个点在fail树上向下走的时候,满足限制的最深点也是单调向下的。于是拿一个栈维护当前点到根的链,用一个单调指针在栈上找就行了。

 #include <bits/stdc++.h>

 #define add(x, y) edge[++tp].v = y; edge[tp].nex = e[x]; e[x] = tp

 const int N = , MO = 1e9 + ;

 struct Edge {
int nex, v;
}edge[N]; int tp; int n, tr[N][], fail[N], len[N], e[N], vis[N], Time, val[N], stk[N], top, ans, tot = , last = ;
char str[N];
std::queue<int> Q;
/*
2
abcababc
abcababc
*/
namespace bf {
typedef unsigned long long uLL;
const uLL B = ;
uLL pw[], h[];
inline void prework() {
pw[] = ;
for(int i = ; i <= n; i++) {
pw[i] = pw[i - ] * B;
h[i] = h[i - ] * B + str[i];
}
return;
}
inline uLL Hash(int l, int r) {
return h[r] - h[l - ] * pw[r - l + ];
}
inline void solve() {
prework();
int ans = ;
for(int i = ; i <= n; i++) {
/// [1, i]
//printf("i = %d \n", i);
int temp = ;
for(int t = i >> ; t; t--) {
//printf("t = %d \n", t);
if(Hash(, t) == Hash(i - t + , i)) {
/// num[i] = t;
++temp;
}
}
ans = 1ll * ans * temp % MO;
}
printf("%d\n", ans);
return;
}
} inline void insert(int f) {
int p = last, np = ++tot;
last = np;
len[np] = len[p] + ;
vis[np] = Time;
while(p && !tr[p][f]) {
tr[p][f] = np;
p = fail[p];
}
if(!p) {
fail[np] = ;
}
else {
int Q = tr[p][f];
if(len[Q] == len[p] + ) {
fail[np] = Q;
}
else {
int nQ = ++tot;
len[nQ] = len[p] + ;
fail[nQ] = fail[Q];
fail[Q] = fail[np] = nQ;
memcpy(tr[nQ], tr[Q], sizeof(tr[Q]));
while(tr[p][f] == Q) {
tr[p][f] = nQ;
p = fail[p];
}
}
}
return;
} inline void clear() {
for(register int i(); i <= tot; i++) {
memset(tr[i], , sizeof(tr[i]));
val[i] = e[i] = fail[i] = len[i] = ;
}
last = tot = ;
tp = ;
return;
} void DFS(int x, int p) {
stk[++top] = x;
/// calc ans x
//printf("x = %d \n", x);
while(p < top && len[stk[p + ]] * <= len[x]) {
++p;
}
if(vis[x] == Time) {
ans = 1ll * ans * (val[stk[p]] + ) % MO;
}
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
val[y] = val[x] + (vis[y] == Time);
DFS(y, p);
}
--top;
return;
} inline void solve() {
scanf("%s", str + );
n = strlen(str + );
/*if(n <= 200) {
bf::solve();
return;
}*/
++Time;
ans = ;
for(register int i(); i <= n; i++) {
insert(str[i] - 'a');
}
for(register int i(); i <= tot; i++) {
add(fail[i], i);
} DFS(, ); /// get val
printf("%d\n", ans);
clear();
return;
} int main() {
int T;
scanf("%d", &T);
while(T--) {
solve();
if(T) memset(str + , , n * sizeof(char));
}
return ;
}

AC代码

这题非常良心的没卡空间。

洛谷P2375 动物园的更多相关文章

  1. 洛谷 P2375 动物园

    题目详情 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法 ...

  2. 【题解】洛谷P2375 [NOI2014] 动物园(KMP)

    洛谷P2375:https://www.luogu.org/problemnew/show/P2375 思路 这道题可以说是完全刷新了本蒟蒻对KMP的理解 感觉对next数组的理解上升到一个新的高度 ...

  3. [洛谷P2375] [NOI2014]动物园

    洛谷题目链接:[NOI2014]动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决 ...

  4. 洛谷 P2375 [NOI2014]动物园 解题报告

    P2375 [NOI2014]动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定 ...

  5. 【KMP】洛谷P2375 [NOI2014]动物园 题解

        一开始的方向应该对了,但是没有想到合理的优化还是没写出来…… 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己 ...

  6. 洛谷 P2375 [NOI2014]动物园

    题目传送门 解题思路: 其实对于一个sum[i],其值就等于sum[next[i]] + sum[next[next[i]]] + ... + 1,然后我们可以记忆化,然后题目里又有一个限制,就是前后 ...

  7. 洛谷P3622 动物园

    题意:给定一个n个元素的圈,m个条件.满足一个条件需要选某些元素或不选另一些元素. 问最多能满足多少条件.每个条件所关联的元素,最远的两个距离不会超过5. 解:想了半天...... 首先能想到断环成链 ...

  8. 洛谷[P3622] 动物园

    状压DP 发现本题中,每个小朋友是否高兴仅取决于其后五个动物的情况,我们可以用状压DP解决本题 首先已处理 num[i][s] 表示对于位置 i ,状态为 s 时有多少在 s 的同学满意 转移方程很好 ...

  9. 洛谷p2375 kmp

    题意 给你一个字符串,让你求一个\(num\)数组,\(num[i]\)为长度为\(i\)的前缀的公共前后缀长度不超过\(\lfloor \frac{i}{2}\rfloor\)的个数, 例如&quo ...

随机推荐

  1. 过滤数组中的空数组array_filter()

    手册查询array_filter()的使用细节时,看到了:If no callback is supplied, all entries of input equal to FALSE (see co ...

  2. centos6.5安装配置NTP,集群各机器间时间同步

    试验环境 提君博客原创 >>提君博客原创  http://www.cnblogs.com/tijun/  << IP 主机名 角色 描述 同步方式 192.168.11.11 ...

  3. 剑指offer(16)栈的压入、弹出序列

    题目: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈 ...

  4. 《笔记》Apache2 mod_wsgi的配置

    接手了一台古老的服务器的还使用的是mod_wsgi,所以需要配置一下.其实这里有点怀念,记得当年自己折腾第一个app的时候,还是个什么都不懂的菜鸡.当时用django搜方案的时候,还不知道有uwsgi ...

  5. Prism框架研究(三)

    这一篇主要用来介绍一下基于Prism Library中的核心服务以及如何配置Container,还有一个重要的部分是如何管理各个组件之间的依赖性,下面就这些内容来做一一的介绍. 1 Prism中的核心 ...

  6. 30行Python代码实现人脸检测

    参考OpenCV自带的例子,30行Python代码实现人脸检测,不得不说,Python这个语言的优势太明显了,几乎把所有复杂的细节都屏蔽了,虽然效率较差,不过在调用OpenCV的模块时,因为模块都是C ...

  7. div中的相对定位与绝对定位

    1.position:relative; 如果对一个元素进行相对定位,首先它将出现在它所在的位置上.然后通过设置垂直或水平位置,让这个元素“相对于”它的原始起点进行移动.(再一点,相对定位时,无论是否 ...

  8. python数据结构与算法第十三天【归并排序】

    1.代码实现 def merge_sort(alist): if len(alist) <= 1: return alist # 二分分解 num = len(alist)/2 left = m ...

  9. php配置-解决大数据超多字段的POST方式提交无法完全接受的问题

    例如:在盘点表的数据提交中出现了POST大量数据超多字段的将近2000个字段,部分字段没有接受:修改方法为修改php.ini 将max_input_var调大,该值默认为1000 max_input_ ...

  10. vscode git设置远程仓库码云

    https://www.cnblogs.com/klsw/p/9080041.html