(HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=5558
S[a…b] means a substring of S ranging from S[a] to S[b] (0≤a≤b<N). If the first i letters have been encrypted, Alice will try to find a magic string P. Assuming P has K letters, P is the longest string which satisfies P=S[T...T+K−1] (0≤T<i,T+K≤N) and P=S[i…i+K−1](i+K≤N). In other words, P is a substring of S, of which starting address is within [0...i−1], and P is also a prefix of S[i...N−1]. If P exists, Alice will append integer Kand T to ciphertext. If T is not unique, Alice would select the minimal one. And then i is incremented by K. If P does not exist, Alice will append -1 and the ASCII code of letter S[i] to ciphertext, and then increment i by 1.
Obviously the first letter cannot be encrypted. That is to say, P does not exist when i=0. So the first integer of ciphertext must be -1, and the second integer is the ASCII code of S[0].
When i=N, all letters are encrypted, and Alice gets the final ciphertext, which consists of many pairs of integers. Please help Alice to implement this method.
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <bitset>
using namespace std;
const int N=1e5+;
char s[N];
int wa[N],wb[N],wv[N],wss[N];
int rankk[N],height[N],sa[N];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(char *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[x[i]=r[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p)
{
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[wv[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return ;
}
void calheight(char *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++) rankk[sa[i]]=i;
for(i=;i<n;height[rankk[i++]]=k)
for(k?k--:,j=sa[rankk[i]-];r[i+k]==r[j+k];k++);
return ;
} int main()
{
int T,Case=;
cin>>T;
while(T--)
{
scanf("%s",s);
int len=strlen(s);
da(s,sa,len+,);
calheight(s,sa,len);
printf("Case #%d:\n",Case++);
int i=;
while(i<len)
{
int pos,k=;
int rk=rankk[i];
int d=height[rk];
for(int j=rk;j>=&&height[j]!=;j--)
{
d=min(d,height[j]);
if(d<k) break;
if(sa[j-]<i&&((d>k)||(d==k&&sa[j-]<pos))) {
k=d; pos=sa[j-];
}
}
if(rk<len){
d=height[rk+];
for(int j=rk+; j<=len&&height[j]!=; j++)
{
d=min(d,height[j]);
if(d<k) break;
if(sa[j]<i&&((d>k)||(d==k&&sa[j]<pos))) {
k=d; pos=sa[j];
}
}
}
if(k) printf("%d %d\n",k,pos),i+=k;
else printf("%d %d\n",-,(int)s[i++]);
}
}
return ;
}
方法二:集合查找
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <bitset>
using namespace std;
const int N=1e5+;
char s[N];
int wa[N],wb[N],wv[N],wss[N];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(char *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[x[i]=r[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p)
{
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[wv[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return ;
}
int rankk[N],height[N],sa[N],m[][N];
void calheight(char *r,int *sa,int n)
{
int i,j,k=;
for(int i=;i<=n;i++) rankk[sa[i]]=i;
for(i=;i<n;height[rankk[i++]]=k)
for(k?k--:,j=sa[rankk[i]-];r[i+k]==r[j+k];k++);
return ;
}
set<int>se;
set<int>:: iterator it1,it2; int main()
{
int T,Case=;
cin>>T;
while(T--)
{
scanf("%s",s);
int len=strlen(s);
da(s,sa,len+,);
calheight(s,sa,len);
memset(m,,sizeof(m));
for(int i=;i<=len;i++)
m[][i-]=height[i];
for(int i=;i<=(int)(log(len)/log());i++)
{
for(int j=;j+(<<i)-<=len;j++)
m[i][j]=min(height[j+(<<(i-))],min(m[i-][j],m[i-][j+(<<(i-))]));
}
printf("Case #%d:\n",Case++);
int tot=,minn=-,maxn=;
se.clear();
se.insert(minn);
se.insert(maxn);
while(tot<len)
{
int k=,p;
int pos=tot;
it1=se.upper_bound(rankk[tot]);
it2=it1;
while(*it1!=maxn)
{
int v=(int)(log(*it1-rankk[tot]+)/log());
int f=min(m[v][rankk[tot]],m[v][*it1-(<<v)+]);
if(f<k||f==) break;
if(f>k||(f==k&&sa[*it1]<p)){
k=f;
p=sa[*it1];
}
it1++;
}
it2--;
while(*it2!=minn){
int v=(int)(log(rankk[tot]-*it2+)/log());
int f=min(m[v][*it2],m[v][rankk[tot]-(<<v)+]);
if(f<k||f==) break;
if(f>k||(f==k&&sa[*it2]<p)){
k=f;
p=sa[*it2];
}
it2--;
}
if(k==) {
printf("%d %d\n",-,(int)s[tot]);
tot++;
}
else {
printf("%d %d\n",k,p);
tot+=k;
}
for(;pos<tot;pos++)
se.insert(rankk[pos]);
}
}
return ;
}
(HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)的更多相关文章
- HDU 5558 Alice's Classified Message(后缀数组+二分+rmq(+线段树?))
题意 大概就是给你一个串,对于每个\(i\),在\([1,i-1]\)中找到一个\(j\),使得\(lcp(i,j)\)最长,若有多个最大\(j\)选最小,求\(j\)和这个\(lcp\)长度 思路 ...
- HUID 5558 Alice's Classified Message 后缀数组+单调栈+二分
http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做 ...
- 2015ACM/ICPC亚洲区沈阳站 Pagodas
Pagodas Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 2015ACM/ICPC亚洲区沈阳站 B-Bazinga
Bazinga Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: ...
- 2015ACM/ICPC亚洲区沈阳站
5510 Bazinga 题意:给出n个字符串,求满足条件的最大下标值或层数 条件:该字符串之前存在不是 它的子串 的字符串 求解si是不是sj的子串,可以用kmp算法之类的. strstr是黑科技, ...
- 2015ACM/ICPC亚洲区沈阳站 Solution
A - Pattern String 留坑. B - Bazinga 题意:找一个最大的i,使得前i - 1个字符串中至少不是它的子串 思路:暴力找,如果有一个串已经符合条件,就不用往上更新 #inc ...
- HDU 5532 / 2015ACM/ICPC亚洲区长春站 F.Almost Sorted Array
Almost Sorted Array Problem Description We are all familiar with sorting algorithms: quick sort, mer ...
- 2015ACM/ICPC亚洲区沈阳站 部分题解
链接在这:http://bak.vjudge.net/contest/132442#overview. A题,给出a,b和n,初始的集合中有a和b,每次都可以从集合中选择不同的两个,相加或者相减,得到 ...
随机推荐
- Azure SQL Database (20) 使用SQL Server 2016 Upgrade Advisor
<Windows Azure Platform 系列文章目录> Azure SQL Database (19) Stretch Database 概览 Azure SQL Da ...
- TODO:Linux安装PHP MongoDB驱动
TODO:Linux安装PHP MongoDB驱动 PHP利于学习,使用广泛,主要适用于Web开发领域. MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统 ...
- JAVA spring hibernate 多数据源配置记录
数据源配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http:// ...
- GridView中数据的汇总方法
首先,在页面添加事件<ASP:GridView OnRowDataBound="Gridview1_DataBound"> 其次,后台具体方法: public void ...
- weblogic配置数据源
启动weblogic 管理服务器,使用管理用户登录weblogic管理控制台 打开管理控制台后,在左侧的树形域结构中,选择服务->数据源. 在右侧的窗口中,选择 新建->一般数据源 ...
- 有关binlog的那点事(三)(mysql5.7.13)
这次我们要探索更精细的binlog内容,上次讨论的Query_event和Rows_event肯定有让你疑惑不解的问题.Query_event中的status-vars环境变量有哪些,Rows_eve ...
- C#设计模式系列:装饰模式(Decorator)
1. 装饰模式简介 装饰模式动态地给一个对象添加额外的职责.例如一幅画有没有画框都可以挂在墙上,画就是被装饰者.但是通常都是有画框的.在挂在墙上之前,画可以被蒙上玻璃,装到框子里,所以在画上加一层画框 ...
- 用js实现放大镜的效果
第一次发博客,还有点小激动,本人现在正在天津上大学,希望以后从事前端这一行业,学习的时间不长,写博客为了记录自己的学习过程和收获,当然也算是巩固.可能写的东西不会像大牛那样高大上,只是一些基本的内容, ...
- Oracel_子查询
SQL子查询 子查询语法 SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table) 子查询 ( ...
- 追根溯源:EntityFramework 实体的状态变化
阅读目录: 1. 应用场景 2. 场景测试 3. 问题分析 4. 追根溯源 5. 简要总结 1. 应用场景 首先,应用程序使用 EntityFramework,应用场景中有两个实体 S_Class(班 ...