【怪物】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 ...
随机推荐
- light oj 1068 数位dp
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> ...
- Shell 语法之用户输入
bash shell 提供了一些不同的方法从用户处获取数据,这些方法包括命令行参数.命令行选项和直接读取键盘输入. 命令行参数 bash shell 将在命令行中输入的所有参数赋值给一些特殊变量,称为 ...
- IO流19(完) --- RandomAccessFile实现数据的插入 --- 技术搬运工(尚硅谷)
原hello.txt文件中的内容:abcdefghijklmn 想要实现的效果是,将xyz插入到abc后面,将文件内容变成:abcxyzdefghijklmn @Test public void te ...
- Spring Cloud Security&Eureka安全认证(Greenwich版本)
Spring Cloud Security&Eureka安全认证(Greenwich版本) 一·安全 Spring Cloud支持多种安全认证方式,比如OAuth等.而默认是可以直接添加spr ...
- CImage 是基于GDI+的,很老的一篇文章,我很久很久以前看到过的
在许多资料上都说CImage类是基于GDI+的,但是为什么是基于GDI+的呢? 因为使用这个类时,并没有加入#include <gdiplus.h> ,也没有在程序开始和结束时分别写GDI ...
- 公司jar包提交到集群的方法
yarn -jar xx.jar 此时包会提交到集群上运行 也可以把jar包放到hbase 的lib下面用hbase jar 方式调用
- 应读的paper
1.Faster R-CNN:https://arxiv.org/abs/1506.01497(已读) 2.FPN(Feature Pyramid Networks for Object Detect ...
- Tensorboard在Win7下chrome无论如何无法连接的情况
后记:其实发现原因后感觉自己很蠢,是自己开了一个软件叫adsafe,会屏蔽一些东西,所以我拼命的用自己的电脑ip都连不上,换成回环地址就好了,把软件关了也可以. 在无数种尝试后,终于在stackove ...
- iOS学习笔记-084.粒子效果——路径移动
https://blog.csdn.net/qiwenmingshiwo/article/details/75806637 粒子效果路径移动一说明1 效果2 步骤分析二代码1 VCViewh2 VCV ...
- javascript基础:事件
事件: 概念:某些组件被执行了某些操作后,触发某些代码的执行 * 事件:某些操作,如:单击,双击,键盘按下了,鼠标移动了 * 事件源:组件.如:按钮 文本输入框.... * 监听器:代码 * ...