【题目】

【题意】

  Jodie和Aiden在做游戏。Jodie在一个长度为l字符串环上走路,他每离开一个就会记下格子当前字符。他让Aiden在他走了一圈后叫他停下来。Aiden决定耍一下Jodie,在他走了k步重复的格后才告诉他。Jodie离开的格子会随机变为一个字符。Jodie走了两次(起点可能不同),每次都走了n(即l+k)步。给出两个长度n的字符串,表示Jodie两次记录的字符串,问l最大可以是多少。 N<=100000

【分析】

  做2次扩展KMP,枚举第二个串的第i位与第一个串对应。一开始容易走入的误区就是直接使用tend2[i]然后判断,但是我们其实不一定让i往后的串越长越好,因为可能前面匹配不了。但是可以确定的是前面的匹配长度已经固定了,即i-1,所以我们只要在第一个串中找到所有的tend1大于等于i-1的x,当x越大,匹配长度越大,所以我们找最大的x使得其tend1[x]大于等于i-1。 可以用二分+rmq或者线段树。 也可以一开始排个序,然后用树状数组动态加减,然后用二分查找。

再放一次扩展KMP部分的代码:(注意那个小于号和小于等于号那里!很重要!):

void get_nt(int x)
{
nt[1]=n;
int mx=0,id;
while(s[x][1+mx]==s[x][2+mx]&&mx<=n) mx++;
nt[2]=mx;id=2;
for(int i=3;i<=n;i++)
{
int now=nt[i-id+1];
if(i+now-1<mx) nt[i]=now;//-> i+now<=mx 注意不要写成i+now-1<=mx!!!
else
{
int j=mx-i+1;
if(j<0) j=0;
while(i+j<=n&&s[x][i+j]==s[x][1+j]) j++;
nt[i]=j;
id=i;mx=i+nt[i]-1;
}
}
} void get_td(int x,int y)
{
int mx=0,id;
while(s[x][1+mx]==s[y][1+mx]) mx++;
td[y][1]=mx;id=1;
for(int i=2;i<=n;i++)
{
int now=nt[i-id+1];
if(i+now-1<mx) td[y][i]=now;
else //i+now-1>=mx
{
int j=mx-i+1;
if(j<0) j=0;
while(i+j<=n&&s[x][1+j]==s[y][i+j]) j++;
td[y][i]=j;
id=i;mx=i+td[y][i]-1;
}
}
}

  

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 2000010 int n;
char s[][Maxn];
int nt[Maxn],td[][Maxn]; int c[Maxn];
struct node
{
int x,y;
}t[Maxn]; bool cmp(node x,node y) {return x.y<y.y;} int mymax(int x,int y) {return x>y?x:y;} void get_nt(int x)
{
nt[]=n;
int mx=,id;
while(s[x][+mx]==s[x][+mx]&&mx<=n) mx++;
nt[]=mx;id=;
for(int i=;i<=n;i++)
{
// mx=id+nt[id]-1;
int now=nt[i-id+];
if(i+now-<mx) nt[i]=now;//-> i+now<=mx 注意不要写成i+now-1<=mx!!!
else
{
int j=mx-i+;
if(j<) j=;
while(i+j<=n&&s[x][i+j]==s[x][+j]) j++;
nt[i]=j;
id=i;mx=i+nt[i]-;
}
}
} void get_td(int x,int y)
{
int mx=,id;
while(s[x][+mx]==s[y][+mx]) mx++;
td[y][]=mx;id=;
for(int i=;i<=n;i++)
{
int now=nt[i-id+];
if(i+now-<mx) td[y][i]=now;
else //i+now-1>=mx
{
int j=mx-i+;
if(j<) j=;
while(i+j<=n&&s[x][+j]==s[y][i+j]) j++;
td[y][i]=j;
id=i;mx=i+td[y][i]-;
}
}
} void add(int x,int y)
{
for(int i=x;i<=n;i+=i&(-i))
c[i]+=y;
} int get_sum(int x)
{
int ans=;
for(int i=x;i>=;i-=i&(-i))
ans+=c[i];
return ans;
} int ffind(int r)
{
int l=;
while(l<r)
{
int mid=(l+r)>>;
if(get_sum(r)-get_sum(mid)>) l=mid+;
else r=mid;
}
if(get_sum(l)==) return ;
return l;
} int main()
{
scanf("%d",&n);
scanf("%s%s",s[]+,s[]+);
get_nt();get_td(,); get_nt();get_td(,); memset(c,,sizeof(c));
for(int i=;i<=n;i++)
{
t[i].x=i;
t[i].y=td[][i];
add(i,);
}
sort(t+,t++n,cmp); int now=,ans=;
for(int i=;i<=n;i++)
{
while(t[now].y<i-&&now<=n)
{
add(t[now].x,-);
now++;
}
int x=ffind(td[][i]+);
if(x) ans=mymax(ans,x+i-);
}
printf("%d\n",ans);
return ;
}

[BEYOND]

2016-08-20 10:55:34

【GDOI2014 DAY2】Beyond (扩展KMP)的更多相关文章

  1. 扩展KMP算法

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

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

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

  3. KMP和扩展KMP

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

  4. UVA5876 Writings on the Wall 扩展KMP

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

  5. hdu4333 扩展KMP

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

  6. 扩展KMP

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

  7. HDU 3336 扩展kmp

    题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模 ...

  8. acdream1116 Gao the string!(扩展KMP)

    今天是字符串填坑的一天,首先填的第一个坑是扩展KMP.总结一下KMP和扩展KMP的区别. 在这里s是主串,t是模式串. KMP可以求出的是以s[i]为结尾的串和 t前缀匹配的最长的长度.假如这个长度是 ...

  9. hdu 4333(扩展kmp)

    题意:就是给你一个数字,然后把最后一个数字放到最前面去,经过几次变换后又回到原数字,问在这些数字中,比原数字小的,相等的,大的分别有多少个.比如341-->134-->413-->3 ...

随机推荐

  1. Amazon EC2上搭建VPN服务器

    Amazon EC2 提供了一年免费试用,Micro Instance,配置是 1G 内存,共享 CPU,和每月 15G 的流量.搭一个 VPN 服务器绰绰有余了.操作系统我选的是 Amazon Li ...

  2. 跨时钟域设计【一】——Slow to fast clock domain

    跨时钟域设计是FPGA设计中经常遇到的问题,特别是对Trigger信号进行同步设计,往往需要把慢时钟域的Trigger信号同步到快时钟域下,下面是我工作中用到的慢时钟域到快时钟域的Verilog HD ...

  3. UML 结构图之包图 总结

    [注] 本文不是包图的基础教程, 只是包图的图形总结. 学习UML图形 推荐阅读<UML参考手册>第2版. http://www.umlchina.com/ 推荐微软的开发软件设计模型 h ...

  4. web开发学习之旅---css第一天

    一.css全称 Cascade Style Sheet层叠样式表 二.css引入方式 行内样式:<h2 style="color:#0F0">Hello World&l ...

  5. 20151225jquery学习笔记---编辑器插件

    编辑器(Editor),一般用于类似于 word 一样的文本编辑器,只不过是编辑为 HTML格式的.分类纯 JS 类型的,还有 jQuery 插件类型的.一. 编辑器简介我们使用的 jQuery 版本 ...

  6. Asp.Net部分面试题

    HTML.javascript部分 1. jQuery的美元符号$有什么作用? 答:个人理解:$指代jquery对象,拥有jquery对象所有的属性和成员 网友理解:在Jquery中,$是JQuery ...

  7. Spring MVC 3.0 返回JSON数据的方法

    Spring MVC 3.0 返回JSON数据的方法1. 直接 PrintWriter 输出2. 使用 JSP 视图3. 使用Spring内置的支持// Spring MVC 配置<bean c ...

  8. 图像储存容器Mat[OpenCV 笔记11]

    IplImage 与 Mat IplImage是OpenCV1中的图像存储结构体,基于C接口创建.在退出之前必须release,否则就会造成内存泄露.在一些只能使用C语言的嵌入式系统中,不得不使用. ...

  9. 基于ECharts 的地图例子

      最近的一个项目要用到显示地图,本来用jq做了一个,但由于客户不满意(确实自己弄的样式效果都不是太理想),于是就上网搜了搜,最后决定基于百度的ECharts来弄地图 本来自己js基础不是很扎实,EC ...

  10. ubuntu 下安装软件,卸载,查看已经安装的软件

    参考网址:http://wiki.ubuntu.org.cn/UbuntuSkills 一般的安装程序用三种: .deb 和.rpm 这两种安装文件 .bundle 这是二进制的安装文件 而 tar. ...