题目大意

给出一个长度为 $n$ 的字符串 $s$ 要求你求出 $s$ 的每一个前缀在 $s$ 中出现的次数之和。$n\le 200000$。

解题思路

暴力的对每一个前缀进行一次匹配,求出出现次数后求和。

那肯定是不行的,复杂的是 $O(n\times (m+n))$ 的,不用想也知道要 TLE 那我们考虑 $KMP$ 中 $next$ 数组的性质:为每一个前缀的前缀和后缀最长的共同子串的长度。

那这不就是说如果 $next[i] = j$ 的话,那么在 $s$ 中 $1\rightarrow j$ 和 $i-next[i]+1\rightarrow i$ 这两个子串是相等的。同时也代表 $1\rightarrow j$ 这个前缀的出现次数多了 $1$。

这就好办了。我们只需要求出 $s$ 的 $next$ 数组,然后就可以算出前缀的出现次数。但是要注意算出的 $next$ 并不能直接求出出现次数。因为 $next$ 数组存储的是位置。所以要一步一步推过来,很容易就能得到一个递推式 $f[i] = f[nxt[i]]+1$ 到最后统计一遍总和就可以得到答案了。

放上代码

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 2e5+, HA = 1e4+;
int T, p, Ans, nxt[maxn], dp[maxn], n;
char s[maxn];
inline void Getnext() {
for(int i=; i<=n; i++) {
p = nxt[i-];
while(p && s[p+] != s[i]) p = nxt[p];
if(s[p+] == s[i]) nxt[i] = p+;
else nxt[i] = ;
}
}
int main() {
scanf("%d", &T);
while (T--) {
memset(nxt, , sizeof(nxt));
memset(dp, , sizeof(dp));
Ans = ;
scanf("%d", &n);
scanf("%s", s+);
Getnext();
dp[] = ;
for(int i=; i<=n; i++) {
dp[i] = dp[nxt[i]] + ;
dp[i] = dp[i] % HA;
}
for(int i=; i<=n; i++)
Ans = (Ans % HA + dp[i] % HA) % HA;
printf("%d\n", Ans);
}
}

最新文章

  1. backup1
  2. 【BZOJ 3150】新Nim游戏
  3. STM32堆栈溢出
  4. iOS开发UI篇—简单介绍静态单元格的使用
  5. JSP/SERVLET入门教程--Servlet 使用入门
  6. java正则表达式 非捕获组详解
  7. Effective_java之二:慎用重载函数
  8. Solr初步学习
  9. java源码剖析: 对象内存布局、JVM锁以及优化
  10. ajax交互数据简单拼装,数组成字符串
  11. ●Joyoi Easy
  12. linux 每个小时释放一次cache
  13. CGI的工作原理
  14. 《DenseNet Models for Tiny ImageNet Classification》课程设计论文
  15. 6 week work 2
  16. 【javascript】谈谈HTML5: Web-Worker、canvas、indexedDB、拖拽事件
  17. 《MySQL必知必会》[07] 管理事务处理
  18. Python3函数式编程
  19. java中实现Comparable接口实现自定义排序
  20. 2018.09.27 bzoj3029: 守卫者的挑战(概率dp)

热门文章

  1. 洛谷P2827 蚯蚓——思路题
  2. js获取下拉框当前选中的值并弹出
  3. Tool:CorelDRAW
  4. linux怎么返回上级目录啊,用cd/命令却这样:bash:cd/:没有那个文件或目录
  5. 使用inet_ntoa() 时编译提示错误:
  6. Poj 3177 Redundant Paths (双连通分支+节点统计)
  7. 数学 FZU 2074 Number of methods
  8. 全面学习ORACLE Scheduler特性(4)创建和管理Schedule
  9. 264 Ugly Number II 丑数 II
  10. Tuple类型的使用