hdu5558 后缀数组
2016-04-06 22:33
417 查看
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
[align=left]Problem Description[/align]
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 (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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
For each test case, output a single line consisting of “[b]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.
[align=left]Sample Input[/align]
2
aaaaaa
aaaaabbbbbaaabbc
[align=left]Sample Output[/align]
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 = 150050; 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 = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[i] = str[i]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i; for(int j = 1; j <= n; j <<= 1) { p = 0; for(int i = n-j; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[y[i]]]++ ; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x,y); p = 1; x[sa[0]] = 0; for(int i = 1; i < n; i++) x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++; if(p >= n) break; m = p; } int k = 0; n--; for(int i = 0; i <= n; i++) Rank[sa[i]] = i; for(int i = 0; i < n; i++) { if(k) k--; int j = sa[Rank[i]-1]; 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 = 1; scanf("%d",&T); while(T--) { scanf("%s",a); int len = 0; for(int i =0;a[i] != '\0'; i++) { str[len++] = a[i]-'a'+1; } str[len] = 0; get_sa(str,sa,Rank,height,len,30); for(int i = 1; i <= len; i++) { if(height[i] == 0) pre[i] = i; else pre[i] = pre[i-1]; } for(int i = len; i >= 1; i--) { if(height[i+1] == 0 || i == len) nex[i] = i; else nex[i] = nex[i+1]; } int i = 0; printf("Case #%d:\n",cas++); while(i < len) { int now = Rank[i]; //i的排名 int k = 0,t = i; int mi = height[now]; for(int j = now-1; j >= pre[now]; j--) { mi = min(mi,height[j+1]); if(mi < k) break; if(sa[j] < i) { if(mi > k || (mi==k && sa[j] < t)) { k = mi; t = sa[j]; } } } if(now+1 <= nex[now]) mi = height[now+1]; for(int j = now+1; 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 == 0) printf("-1 %d\n",a[i]); else printf("%d %d\n",k,t); if(k) i+=k; else i++; } } return 0; }
相关文章推荐
- SVN命令使用详解
- leetcode——2——Add Two Numbers
- kernel_init寻找init并执行
- 实例详解机器学习如何解决问题
- androidStudio出现R无法识别比对下面build.gradule
- Android学习之Soft Keyboard使用文档翻译
- Mac电脑编程问题汇总.
- 字符串排序
- 复利计算5.0
- for 循环学习,输出
- LeetCode(28)-Remove Duplicates from Sorted Array
- xml入门及bom
- spring+tomcat8实现websocket
- Tsinsen A1129 税收与补贴问题
- LeetCode(28)-Remove Duplicates from Sorted Array
- LeetCode(28)-Remove Duplicates from Sorted Array
- hdu2588(欧拉函数的应用)
- Python开发测试工具(二)—Monkey工具的优化
- 详解SQL Server连接(内连接、外连接、交叉连接)
- 复利计算-结对编程