【怪物】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 ...
随机推荐
- Django项目:CRM(客户关系管理系统)--57--47PerfectCRM实现CRM客户报名流程02
图片另存为 16*16 名字修改为 bpm_logo.jpg /*! *bootstrap.js * * Bootstrap v3.3.7 (http://getbootstrap.co ...
- MySQL命令行本地登陆,远程登陆MySQL 的快捷键
1.进入Mysql的安装目录bin文件夹下 如默认路径: cd C:\Program Files\MySQL\MySQL Server 8.0\bin 2.本地登录MySQL 命令:mysql -u ...
- Java基础程序与面向对象
首先,我们需要了解和知道一些Java的基本概念: 程序编译过程:.java文件会通过编译器--被编译成一个. class字节码文件---再由虚拟机运行.class文件解释运行Java程序. 编码规范: ...
- host ngnix zull
1.浏览器解析域名:www.baidu.com 2.由本地host解析得到IP:127.0.0.1 3.向IP传递请求,IP所在PC的Ngnix监听80端口. 4.IP所以PC收到请求后,nginx由 ...
- 利用Python覆盖图像的某一部分,即改变图形一块区域(Region)的RGBA值
原图如下: 改变过后的图如下: 查阅API写法如下: from PIL import Image from PIL import ImageDraw pilim = Image.open('1.jpg ...
- 解决JSP调用JavaBean出现乱码问题
解决JSP调用JavaBean出现乱码问题 话不多说放代码 144 Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style D ...
- 彭亮—Python学习
1.1 Python简单介绍 1.2 安装Python和配置环境 1.配置Python 1.1 下载Python(直接去官网下载就可以) 1.2 安装Python(点解默认安装即可 ...
- 【vue】/vue-ele-project
作者大大的地址是:https://github.com/JinwenXie/vue-ele-project 还是老办法,先运行项目看看效果 我不算是外卖爱好者,不过觉得那个添加商品到购物车的动画效果很 ...
- H5C3--盒子模型
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 锋利的jQuery学习笔记之jQuery选择器
在介绍jQuery选择器之前,先简单介绍一下CSS选择器---> 一.CSS选择器 常见的CSS选择器有以下几种: 选择器 语法 描述 示例 标签选择器 E{CSS规则} 以文档元素为选择符 t ...