博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[后缀数组]JZOJ 3337 wyl889的TLE
阅读量:5201 次
发布时间:2019-06-13

本文共 2947 字,大约阅读时间需要 9 分钟。

Description

wyl8899今天也很刻苦的在做老师布置下来的题目!
这一天老师布置的题目是这样的:
给出两个仅含小写字母的字符串A和B,输出最大的k,使得A[1..k]是B的子串。
A和B的长度都不会超过50000。
很显然他并不知道正确的做法,但是他居然卡着时间过掉了老师给的数据!
你找到了他提交给老师的程序,经过测试你惊讶的发现,他的程序运行时间恰好是最终答案,单位是毫秒。
你现在找到了老师给的数据中的一笔,你决定至多修改A串中的一个字母,使得他的程序尽可能的慢。
现在,你能告诉我修改数据之后他的程序在这个测试点的运行时间么?(单位当然还是毫秒)
 

Input

两行,每行一个仅含小写字母的字符串,分别是A和B。
保证A和B的长度都不超过50000。

Output

你修改数据之后,wyl8899的程序在这个测试点的运行时间,单位是毫秒。
 

Sample Input

输入1: adbc aabbabd 输入2: aab aabcc  

Sample Output

输出1: 3 输出2: 3
 

Data Constraint

保证A和B的长度都不超过50000。
 

Hint

数据是在Windows下生成的,测评环境是Linux。
由于换行符的差异,对于C/C++选手,请不要使用gets(s)读入一行字符,建议使用scanf("%s",s)的形式。
Pascal选手直接使用readln()读入一行即可,理论上readln()不会受到不同换行符的影响。

分析

发现可以枚举端点i,然后修改字符前的长度是len=LCP(B[i..m],A)

则ans=max(len+1+LCP(B[i+len+1..m],A[len+2..n]))

考场看到LCP时 心 肺 停 止

背完SA板子以后随便搞搞就欧克了

 

#include 
#include
#include
using namespace std;const int N=1e6+10;int n,n1,n2,m;int c[N],x[N],y[N],sa[N],rk[N],height[(1<<21)+1][21],pow[21],ans;char s[N],s2[N];int MIN(int l,int r) { if (l>r) swap(l,r); l++; int ans=2147483647; for (int k=20;k>=0;k--) if (l+pow[k]-1<=r) { ans=min(ans,height[l][k]); l+=pow[k]; } return ans;}void Solve() { int len,l; for (int i=1;i<=n2;i++) { len=min(min(n1,n2-i+1),MIN(rk[i],rk[n2+1])); ans=max(ans,min(min(n1,n2-i+1),len+1)); ans=max(ans,min(min(n1,n2-i+1),len)); l=min(min(n1,n2-i+1)-len-1,MIN(rk[i+len+1],rk[n2+len+2])); ans=max(ans,len+1+l); }}void SA() { memset(c,0,sizeof c); for (int i=1;i<=n;i++) c[x[i]=s2[i]]++; for (int i=1;i<=m;i++) c[i]+=c[i-1]; for (int i=n;i;i--) sa[c[x[i]]--]=i; for (int k=1;k<=n;k<<=1) { memset(c,0,sizeof c);int cnt=0; for (int i=n-k+1;i<=n;i++) y[++cnt]=i; for (int i=1;i<=n;i++) if (sa[i]>k) y[++cnt]=sa[i]-k; for (int i=1;i<=n;i++) c[x[i]]++; for (int i=1;i<=m;i++) c[i]+=c[i-1]; for (int i=n;i;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y);cnt=0; x[sa[1]]=++cnt; for (int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?cnt:++cnt; if (cnt==n) break; m=cnt; }}void Get_Height() { for (int i=1;i<=n;i++) rk[sa[i]]=i; int k=0; for (int i=1;i<=n;i++) { if (rk[i]==1) continue; k=max(0,k-1); int j=sa[rk[i]-1]; while (s2[j+k]==s2[i+k]&&i+k<=n&&j+k<=n) k++; height[rk[i]][0]=k; }}void RMQ() { for (int k=1;k<=20;k++) for (int i=1;i<=n;i++) height[i][k]=min(height[i][k-1],height[i+pow[k-1]][k-1]);}int main() { scanf("%s",s+1);scanf("%s",s2+1); n1=strlen(s+1);n=strlen(s2+1);m='z';n2=n; for (int i=n+1;i<=n1+n;i++) s2[i]=s[i-n]; n+=n1; pow[0]=1; for (int i=1;i<=20;i++) pow[i]=pow[i-1]<<1; SA();memset(height,0x7f,sizeof height); Get_Height(); RMQ(); Solve(); printf("%d",ans);}
View Code

 

转载于:https://www.cnblogs.com/mastervan/p/11166674.html

你可能感兴趣的文章
服务器被疑似挖矿程序植入107.174.47.156,发现以及解决过程(建议所有使用sonatype/nexus3镜像的用户清查一下)...
查看>>
类型“XXX”的控件“XXXX”必须放在具有 runat=server 的窗体标记内。
查看>>
JQuery 学习
查看>>
session token两种登陆方式
查看>>
C# ArrayList
查看>>
IntelliJ IDEA 12集成Tomcat 运行Web项目
查看>>
java,多线程实现
查看>>
个人作业4-alpha阶段个人总结
查看>>
android smack MultiUserChat.getHostedRooms( NullPointerException)
查看>>
递归-下楼梯
查看>>
实用的VMware虚拟机使用技巧十一例
查看>>
Docker技术入门之---为镜像添加SSH服务(7)
查看>>
Docker技术入门之---网络配置(8)
查看>>
监控工具之---Prometheus 安装详解(三)
查看>>
Azure Iaas基础之---创建虚拟机
查看>>
Grafana Configuration 参数详解(1)
查看>>
监控工具之---Prometheus数据可视化Grafana(七)
查看>>
监控工具之---Prometheus表达式promQL生产中应用(五)
查看>>
使用POI操作Excel时对事先写入模板的公式强制执行
查看>>
centos7下python3和pycharm安装
查看>>