(HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)
Posted 茶飘香~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)相关的知识,希望对你有一定的参考价值。
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=5558
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 Nlowercase 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 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.
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.
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
Source
Recommend
题意:输入一个只含有小写英文字母的字符串s[], 现在进行计算,对于当前位置i 在0~i-1 中找到j 使得后缀suffix[i] 和 suffix[j] 的公共前缀最长(设公共前缀长为k),输出长度和j,如果有多个j公共前缀长度一样,输出最小的j ,然后i=i+k 重复上述过程,直至i>=len;
思路:先用后缀数组模板计算出名次数组和后缀数组 及最长公共前缀height[]数组 ,然后对于i 求出i的排名,然后根据i的排名,向比i大和小的排名找,取一个最大值;
代码如下:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <bitset> using namespace std; const int N=1e5+5; 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=0;i<m;i++) wss[i]=0; for(i=0;i<n;i++) wss[x[i]=r[i]]++; for(i=1;i<m;i++) wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) sa[--wss[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) wss[i]=0; for(i=0;i<n;i++) wss[wv[i]]++; for(i=1;i<m;i++) wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) sa[--wss[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return ; } void calheight(char *r,int *sa,int n) { int i,j,k=0; for(i=1;i<=n;i++) rankk[sa[i]]=i; for(i=0;i<n;height[rankk[i++]]=k) for(k?k--:0,j=sa[rankk[i]-1];r[i+k]==r[j+k];k++); return ; } int main() { int T,Case=1; cin>>T; while(T--) { scanf("%s",s); int len=strlen(s); da(s,sa,len+1,130); calheight(s,sa,len); printf("Case #%d:\n",Case++); int i=0; while(i<len) { int pos,k=0; int rk=rankk[i]; int d=height[rk]; for(int j=rk;j>=1&&height[j]!=0;j--) { d=min(d,height[j]); if(d<k) break; if(sa[j-1]<i&&((d>k)||(d==k&&sa[j-1]<pos))) { k=d; pos=sa[j-1]; } } if(rk<len){ d=height[rk+1]; for(int j=rk+1; j<=len&&height[j]!=0; 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",-1,(int)s[i++]); } } return 0; }
以上是关于(HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)的主要内容,如果未能解决你的问题,请参考以下文章
线段树HDU 5493 Queue (2015 ACM/ICPC Asia Regional Hefei Online)
贪心模拟HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)
HDU 5446 Unknown Treasure(中国剩余定理+卢卡斯定理)——2015 ACM/ICPC Asia Regional Changchun Online
动态规划HDU 5492 Find a path (2015 ACM/ICPC Asia Regional Hefei Online)
二分最长上升子序列HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)
HDU 5475 An easy problem(用大数模板,你就上当了)——2015 ACM/ICPC Asia Regional Shanghai Online