Alice's Classified Message

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 312    Accepted Submission(s): 122

Problem Description
Alice wants to send a classified message to Bob. She tries to encrypt the message with her original encryption method. The message is a string S, which consists of N lowercase letters.

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 K and 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.

 
Input
The first line of input contains an integer T, which represents the number of test cases (T≤50). Each test case contains a line of string, which has no more than 100000 lowercase letters. It is guaranteed that the total length of the strings is not greater than 2×106.
 
Output
For each test case, output a single line consisting of “Case #X:” first. X is the test case number starting from 1. Output the ciphertext in the following lines. Each line contains two integers separated by a single space.
 
Sample Input
2
aaaaaa
aaaaabbbbbaaabbc
 
Sample Output
Case #1:
-1 97
5 0
Case #2:
-1 97
4 0
-1 98
4 5
5 2
-1 99
 /*
hdu5558 后缀数组 从[1,n]对于每个i,求suff[j](j < i)与suff[i]的最长公共前缀,
如果有多个,取最小的那个 我们可以通过后缀数组先求出,如果i-1和i,i和i+1都有公共前缀,
那么i-1和i+1也有公共前缀,所以可以先处理出每个i的左右界限。然后对于i左右扫描一下即可 然后枚举i,从pre[i]-nex[i]找到合适的结果即可 hhh-2016-03-10 18:17:04
*/
#include <algorithm>
#include <cmath>
#include <queue>
#include <iostream>
#include <cstring>
#include <map>
#include <cstdio>
#include <vector>
#include <functional>
#define lson (i<<1)
#define rson ((i<<1)|1)
using namespace std;
typedef long long ll;
const int maxn = ; int t1[maxn],t2[maxn],c[maxn];
bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] &&r[l+a] == r[l+b];
} void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
{
n++;
int p,*x=t1,*y=t2;
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[i] = str[i]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i>=; i--) sa[--c[x[i]]] = i;
for(int j = ; j <= n; j <<= )
{
p = ;
for(int i = n-j; i < n; i++) y[p++] = i;
for(int i = ; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[y[i]]]++ ;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i >= ; i--) sa[--c[x[y[i]]]] = y[i]; swap(x,y);
p = ;
x[sa[]] = ;
for(int i = ; i < n; i++)
x[sa[i]] = cmp(y,sa[i-],sa[i],j)? p-:p++;
if(p >= n) break;
m = p;
}
int k = ;
n--;
for(int i = ; i <= n; i++)
Rank[sa[i]] = i;
for(int i = ; i < n; i++)
{
if(k) k--;
int j = sa[Rank[i]-];
while(str[i+k] == str[j+k]) k++;
height[Rank[i]] = k;
}
} int pre[maxn],nex[maxn];
int Rank[maxn],height[maxn];
int sa[maxn],str[maxn];
char a[maxn];
int len; int main()
{
int T,cas = ;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
int len = ;
for(int i =;a[i] != '\0'; i++)
{
str[len++] = a[i]-'a'+;
}
str[len] = ;
get_sa(str,sa,Rank,height,len,); for(int i = ; i <= len; i++)
{
if(height[i] == )
pre[i] = i;
else
pre[i] = pre[i-];
} for(int i = len; i >= ; i--)
{
if(height[i+] == || i == len) nex[i] = i;
else nex[i] = nex[i+];
} int i = ;
printf("Case #%d:\n",cas++);
while(i < len)
{
int now = Rank[i]; //i的排名
int k = ,t = i;
int mi = height[now];
for(int j = now-; j >= pre[now]; j--)
{
mi = min(mi,height[j+]);
if(mi < k)
break;
if(sa[j] < i)
{
if(mi > k || (mi==k && sa[j] < t))
{
k = mi;
t = sa[j];
}
}
}
if(now+ <= nex[now]) mi = height[now+];
for(int j = now+; j <= nex[now]; j++)
{
mi = min(mi,height[j]);
if(mi < k)
break;
if(sa[j] < i)
{
if(mi > k || (mi==k && sa[j] < t))
{
t = sa[j];
k = mi;
}
}
} if(k == ) printf("-1 %d\n",a[i]);
else printf("%d %d\n",k,t);
if(k) i+=k;
else i++;
}
}
return ;
}
												

hdu5558 后缀数组的更多相关文章

  1. HDU5558 Alice's Classified Message(合肥区域赛 后缀数组)

    当初合肥区域赛的题(现场赛改了数据范围就暴力过了),可惜当初后缀数组算法的名字都没听过,现在重做下. i从1到n - 1,每次枚举rank[i]附近的排名,并记录当起点小于i时的LCP(rank[i] ...

  2. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  3. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  4. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  5. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  6. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  7. 后缀数组(suffix array)详解

    写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...

  8. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  9. 【BZOJ-2119】股市的预测 后缀数组

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 334  Solved: 154[Submit][Status][Discuss ...

随机推荐

  1. wireshark抓包分析tcp连接与断开

    其实对于网络通信的学习,最好还是能够自己抓到包详细地一下,不然只单单通过文字和图的描述印象不够深刻.本文通过实际的抓包操作来看一下tcp的连接与断开是怎样的. 首先需要去https://www.wir ...

  2. 《javascript设计模式与开发实践》阅读笔记(12)—— 享元模式

    享元模式 享元(flyweight)模式是一种用于性能优化的模式,"fly"在这里是苍蝇的意思,意为蝇量级.享元模式的核心是运用共享技术来有效支持大量细粒度的对象. 享元模式的核心 ...

  3. [笔试题目]使用Stringbuffer无 参的构造函数创建 一个对象时,默认的初始容量是多少? 如果长度不够使用了,自动增长多少倍?

    [笔试题目] 使用Stringbuffer无 参的构造函数创建 一个对象时,默认的初始容量是多少? 如果长度不够使用了,自动增长多少倍? StringBuffer 底层是依赖了一个字符数组才能存储字符 ...

  4. MySQL关系表查询两个表的数据

    如下,有四张表:游戏类型表,游戏表,点卡和游戏关系表,点卡表 CREATE TABLE `gamesType`( `tId` INT AUTO_INCREMENT NOT NULL PRIMARY K ...

  5. Tomcat性能优化及JVM内存工作原理

    Java性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收,下面会重点介绍这方面) 代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容如下: 1. ...

  6. python random 模块的用法

    Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...

  7. Docker学习笔记 - 在运行中的容器内启动新进程

    docker psdoker top dc1 # 容器情况# 在运行中的容器内启动新进程docker exec [-d] [-i] [-t] 容器名 [command] [args]docker ex ...

  8. PV 动态供给 - 每天5分钟玩转 Docker 容器技术(153)

    前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision). 与之对应的是动态供给(Dynamical Provi ...

  9. fetch简明学习

    前面的话 Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应.它还提供了一个全局 fetch()方法,该方法提供了一种简单,合乎逻辑的方式来跨网 ...

  10. Ecplise 配置本地 https 测试

    今天做项目,需要关联Office 365.为了实现Office365的用户邮件信息与项目的实时同步,需要建立webhook订阅. Office 365 API 连接  https://graph.mi ...