【怪物】KMP畸形变种——扩展KMP
问题
参考51nod1304这道题;
很显然我们要求的是S的每个后缀与S的最长公共前缀的长度之和。
暴力
假设我们把next[i]表示为第i个后缀与S的最长公共前缀的长度。
现在我们想了:这个next数组,如果暴力来求的话,时间复杂度是O(n2)。
这是我们回忆一下KMP:KMP物尽其用,然后呢就把求fail的速度提高到了O(n)。
那么我们在求next数组的时候,可不可以也使用这样的想法来物尽其用,尽可能地去除重复的匹配呢?
答案是肯定的。
引入扩展KMP
假设要处理出S的next数组,现在已经处理出前s的next了。
现在要求出下一个位置x的next。
其中维护一个li,使得li=max{next[id]}(id∈[1,s])。
由next[id]的定义,我们知道S[id..li]=S[1..next[id]]。
推得S[x..li]=S[1+x−id..next[id]]。
如果id>1,那么1+x−id<x,进一步next[1+x−id]我们已经是知道的了。
于是就有S[x..li]=S[1..next[1+x−id]]。
目前为止,我们很容易看出,x往后的next[1+x−id]这一段是可以不用匹配的。
但我们需要再分类一下:
1.x+next[1+x-id]-1<li
这种情况显然是next[x]=next[1+x−id]。
因为在li范围内,next[1+x−id]是极大的。
所以next[x]不会比next[1+x−id]更大。
2.x+next[1+x-id]-1>=li
这种情况虽然我们可以知道,[x,li]这一段是可以不用匹配的。
但是li以后的情况我们都是未知的。
那么我们暴力匹配来推进li。
于是乎就会有新的li=next[x],id=x。
重复上述过程,我们可以求出所有的next。
显然时间复杂度只与li的推进有关,即为O(n)。
回到本题
使用扩展KMP求出next后,求和即可。
我的博客。
扩展KMP的完全体
事实上本题只是扩展KMP的退化。
扩展KMP可以用于求一个串S的所有后缀与目标串T的最长公共前缀的的长度。
想法与求next数组一样。
设要求的东西叫ext。
其中维护一个li,使得li=max{ext[id]}(id∈[1,s])。
同理推得S[x..li]=T[1..next[1+x−id]],其中next关于T。
那么依然分类讨论,即可求出ext。
最后贴上一个求next的程序
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="ex1304.in";
const char* fout="ex1304.out";
const int inf=0x7fffffff;
const int maxn=1000007;
int n,i,j,k,limit,id;
ll ans;
char a[maxn];
int ne[maxn];
int main(){
scanf("%s",a+1);
n=strlen(a+1);
limit=0;
id=0;
ne[1]=n;
for (i=2;i<=n;i++){
j=ne[i-id+1];
if (i+j-1<limit) ne[i]=j;
else{
j=max(0,limit-i+1);
for (;j+i<=n;j++) if (a[i+j]!=a[j+1]) break;
if (i+j-1>limit){
limit=i+j-1;
id=i;
}
ne[i]=j;
}
}
for (i=1;i<=n;i++) ans+=ne[i];
printf("%lld",ans);
return 0;
}
【怪物】KMP畸形变种——扩展KMP的更多相关文章
- KMP之Z-function (扩展kmp)
http://codeforces.com/blog/entry/3107 // s[0, ..., n-1], z[0] = 0// z[i] is the length of the longes ...
- 扩展KMP——算法总结,来自于 迷路的鸽子
扩展kmp LRH 所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大. 1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀 ...
- 扩展kmp——原创
扩展kmp LRH 所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大. 1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀 ...
- 扩展KMP算法
一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...
- 扩展KMP --- HDU 3613 Best Reward
Best Reward Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...
- KMP和扩展KMP
文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...
- UVA5876 Writings on the Wall 扩展KMP
扩展KMP的简单题. #include<stdio.h> #include<string.h> #define maxn 51010 char s[maxn],t[maxn]; ...
- hdu4333 扩展KMP
慢慢研究可以发现,可以用扩展kmp来求.由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次. 先求如果next[]>0&& ...
- 扩展KMP
刘雅琼论文 http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 论文讲的非常详细. 给定母串S,子串T,n=strlen(S),m=st ...
随机推荐
- 阿里云提供全托管 ZooKeeper
自 2010 年左右第一次引入以来,Apache ZooKeeper 目前在阿里巴巴集团内部已经有了将近 10 年的发展,使用的场景非常广泛,基于 ZooKeeper 强一致性的特点,被用在了分布式锁 ...
- Redis开发及管理实战
目录 Redis数据类型 字符串 String string类型操作 字典 Hash 列表 List 集合 Set 有序集合 SortedSet 生产消费模型 Redis事务管理 事务命令 示例 Re ...
- C语言作用域、链接属性和存储类型
C/C++中作用域详解 作用域 编译器可以确认的4种作用域-代码块作用域.文件作用域.函数作用域和原型作用域,一般来说,标识符(包括变量名和函数名)声明的位置决定它的作用域. (1)代码块作用域 一对 ...
- python 运行python -m pip list 出现错误
1.出现如下错误提示 2解决方案 解决方法:(windows)在C:\Users{用户名}\ 目录下创建名称为pip的文件夹,里面创建文本文件,内容为 [list] format=columns 保存 ...
- 实习面试总结(只写了昨天腾讯的面试和拿到offer的一个小公司, 有空再把前面的补上吧)
一个月来面了大大小小的公司有近10个,还是总结一下吧,希望对大家有点用处. 我想说的是,大学四年,如果不会继续读研深造,那么你需要做的不仅仅是疯狂的做项目,或者单独的学算法. 最好的方式就是都了解一点 ...
- idea使用及其快捷键(Jetbrains很多是通用的)(转)
Java程序员肯定会使用idea进行开发,因为其非常强大,很好用,而且可以很傻瓜式导入gradle,用来做SSM项目也很简单 学生是可以使用教育邮箱或者上床学生证使用免费的jetbrains全家桶的, ...
- 初探.NET CORE WEB API(RESTful风格)
前面有4篇系列博客 (一)Asp.net web api中的坑-[找不到与请求 URI匹配的 HTTP 资源] (二)Asp.net web api中的坑-[http get请求中的参数] (三)As ...
- MATLAB---dir函数
dir函数是最常用的转换路径的函数,可以获得指定文件夹下的所有子文件夹和文件,并存放在一个文件结构的数组中,这个数组各结构体内容如下: name -- 文件名 date -- 修改日期 b ...
- 用Python的requests库作接口测试——对响应进行迭代
使用 requests.Response.iter_lines() 方法,可以很方便地对流式API(例如 Twitter的流式API )的响应进行迭代. 简单地设置 stream 为 True 便可以 ...
- TZ_05_Spring_annotation常见注解
Spring常用的注解大全和解释 注解 解释 @Controller 组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类 ...