问题

参考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的更多相关文章

  1. 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 ...

  2. 扩展KMP——算法总结,来自于 迷路的鸽子

    扩展kmp                 LRH 所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大. 1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀 ...

  3. 扩展kmp——原创

    扩展kmp                 LRH 所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大. 1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀 ...

  4. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  5. 扩展KMP --- HDU 3613 Best Reward

    Best Reward Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...

  6. KMP和扩展KMP

    文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...

  7. UVA5876 Writings on the Wall 扩展KMP

    扩展KMP的简单题. #include<stdio.h> #include<string.h> #define maxn 51010 char s[maxn],t[maxn]; ...

  8. hdu4333 扩展KMP

    慢慢研究可以发现,可以用扩展kmp来求.由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次. 先求如果next[]>0&& ...

  9. 扩展KMP

    刘雅琼论文 http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 论文讲的非常详细. 给定母串S,子串T,n=strlen(S),m=st ...

随机推荐

  1. light oj 1068 数位dp

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> ...

  2. Shell 语法之用户输入

    bash shell 提供了一些不同的方法从用户处获取数据,这些方法包括命令行参数.命令行选项和直接读取键盘输入. 命令行参数 bash shell 将在命令行中输入的所有参数赋值给一些特殊变量,称为 ...

  3. IO流19(完) --- RandomAccessFile实现数据的插入 --- 技术搬运工(尚硅谷)

    原hello.txt文件中的内容:abcdefghijklmn 想要实现的效果是,将xyz插入到abc后面,将文件内容变成:abcxyzdefghijklmn @Test public void te ...

  4. Spring Cloud Security&Eureka安全认证(Greenwich版本)

    Spring Cloud Security&Eureka安全认证(Greenwich版本) 一·安全 Spring Cloud支持多种安全认证方式,比如OAuth等.而默认是可以直接添加spr ...

  5. CImage 是基于GDI+的,很老的一篇文章,我很久很久以前看到过的

    在许多资料上都说CImage类是基于GDI+的,但是为什么是基于GDI+的呢? 因为使用这个类时,并没有加入#include <gdiplus.h> ,也没有在程序开始和结束时分别写GDI ...

  6. 公司jar包提交到集群的方法

    yarn -jar xx.jar 此时包会提交到集群上运行 也可以把jar包放到hbase 的lib下面用hbase jar 方式调用

  7. 应读的paper

    1.Faster R-CNN:https://arxiv.org/abs/1506.01497(已读) 2.FPN(Feature Pyramid Networks for Object Detect ...

  8. Tensorboard在Win7下chrome无论如何无法连接的情况

    后记:其实发现原因后感觉自己很蠢,是自己开了一个软件叫adsafe,会屏蔽一些东西,所以我拼命的用自己的电脑ip都连不上,换成回环地址就好了,把软件关了也可以. 在无数种尝试后,终于在stackove ...

  9. iOS学习笔记-084.粒子效果——路径移动

    https://blog.csdn.net/qiwenmingshiwo/article/details/75806637 粒子效果路径移动一说明1 效果2 步骤分析二代码1 VCViewh2 VCV ...

  10. javascript基础:事件

    事件: 概念:某些组件被执行了某些操作后,触发某些代码的执行 *  事件:某些操作,如:单击,双击,键盘按下了,鼠标移动了 *  事件源:组件.如:按钮   文本输入框.... *  监听器:代码 * ...