Ural 1706. Cipher Message 2 后缀数组
来源:互联网 发布:北京java工资水平 编辑:程序博客网 时间:2024/05/20 23:30
1706. Cipher Message 2
Time limit: 3.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Müller had been suspecting for a long time that Stierlitz had been sending cipher messages to the USSR from time to time. And now Müller almost got the proof of that. Rummaging through Stierlitz's papers, he found a strange sequence of digits written on a clean sheet of paper. He guessed that it was a cipher message and called Stierlitz for questioning. But Stierlitz calmly answered that the digits were the number of a lottery-ticket that he had written in order not to forget it. Stierlitz had never been so close to a failure: there were the coordinates of Hitler's bunker on the sheet.
For transmitting the data to the center, Stierlitz used the following algorithm:
- The input is a string s = s1s2…sn.
- A key k is chosen; it is a positive integer smaller than n.
- For every symbol si of the string, the following procedure is applied:
- The string qi is considered consisting of k consecutive symbols of the string s starting from the ith: qi = sisi + 1…si + k − 1. If there are less than k symbols till the end of the string, then the remaining symbols are taken from the beginning of the string: qi =si…sns1…si + k − 1 − n.
- For the string qi, the number of its different nonempty substrings mi is calculated.
- The sequence m1, m2, …, mn is the output of the algorithm.
It is not easy to cipher with this algorithm, and how to decode the messages only the Soviet intelligence service knows. You are given a chance to feel yourself the famous Stierlitz for several minutes.
Input
In the first line you are given the key k, 1 ≤ k ≤ 1000. The second line contains the string s you are supposed to cipher. The string consists of lowercase English letters, and its length is strictly greater than k and does not exceed 4000.
Output
Output the numbers m1, m2, …, mn separated with spaces.
Sample
3abaccc
5 6 5 3 5 6
Problem Author: Dmitry Ivankov
Problem Source: The 13th Urals Collegiate Programing Championship, April 04, 2009
Problem Source: The 13th Urals Collegiate Programing Championship, April 04, 2009
题意:二战的背景,为了将数据传送到中心,Stierlitz使用以下算法:
输入一个字符串s = s1s2…sn.
选择密钥K,是一件正面小于n的整数。
对于每一个符号SI的字符串,下面的程序适用于:
被认为是由k个连续符号的字符串s从i开始串qi :qi = sisi + 1…si + k − 1.。如果有小于k符号,直到结尾的字符串,那么剩下的符号都取自开头的字符串:qi =si…sns1…si + k − 1 − n.。
对于串qi,输出其不同的非空的子串中号的数量m1, m2, …, mn。
输入一个字符串s = s1s2…sn.
选择密钥K,是一件正面小于n的整数。
对于每一个符号SI的字符串,下面的程序适用于:
被认为是由k个连续符号的字符串s从i开始串qi :qi = sisi + 1…si + k − 1.。如果有小于k符号,直到结尾的字符串,那么剩下的符号都取自开头的字符串:qi =si…sns1…si + k − 1 − n.。
对于串qi,输出其不同的非空的子串中号的数量m1, m2, …, mn。
首先先把字符串复制一遍,之后再利用height相减即为k个的字符串
#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int MAX = 8005;int sa[MAX], rk[MAX], height[MAX];int wa[MAX], wb[MAX], wv[MAX], wd[MAX];int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a+l] == r[b+l];}int min(int a,int b){ return a<b? a:b;}void da(int *r, int n, int m) // 倍增算法0(nlgn)。m是r中元素的最大值{ int i, j, p, *x = wa, *y = wb, *t; for(i = 0; i < m; i ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[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 ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[wv[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[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 ++; } }}void calHeight(int *r, int n) // 求height数组。{ int i, j, k = 0; for(i = 0; i < n; i ++) rk[sa[i]] = i; for(i = 0; i < n; height[rk[i ++]] = k) { for(k ? k -- : 0, j = sa[rk[i]-1]; r[i+k] == r[j+k]; k ++); }}char str[8000];int r[8005];int main(){ int k; int i; while(~scanf("%d",&k)) { scanf("%s",str); int l=strlen(str); int w=l; for(i=0; i<l; i++) str[l+i]=str[i]; l=l+l; str[l]='#'; l++; int j; for(i=0; i<w; i++) { int cnt=0; for(j=i; j<i+k; j++) r[cnt++]=str[j]; r[cnt++]=0; da(r,cnt,260); calHeight(r,cnt); int k,ret=0; for(k=1; k<cnt; k++) { ret+=cnt-1-sa[k]-height[k]; } printf("%d",ret); if(i!=w-1) printf(" "); else printf("\n"); } } return 0;}
- Ural 1706. Cipher Message 2 后缀数组
- Ural 1590. Bacon’s Cipher 后缀数组
- ural 1654 Cipher Message
- URAL 1654 - Cipher Message
- ural 1654. Cipher Message
- Ural 1654 Cipher Message
- Ural 1654. Cipher Message
- Ural 1654. Cipher Message
- URAL 1654 Cipher Message
- ural 1654. Cipher Message
- URAL 1654 Cipher Message(栈)
- URAL 1996 Cipher Message 3 (FFT + KMP)
- ural 1996. Cipher Message 3 KMP+FFT
- 【ural】1996. Cipher Message 3【FFT+KMP】
- URAL 1654. Cipher Message (STL stack)
- URAL 1996 Cipher Message 3 FFT + KMP
- URAL 1996 Cipher Message 3 (FFT + KMP)
- URAL 1996 Cipher Message 3 FFT KMP
- 注意virtual的几点!
- Android 实时获取麦克风输入音量的代码
- setsid()
- AndroidSDKManager无法更新问题
- 创建表格(Table)
- Ural 1706. Cipher Message 2 后缀数组
- 各个平台的mysql重启命令
- 修改android模拟器的默认安装路径
- Linux2.6--虚拟文件系统
- 【JavaMe开发:绘制文本框TextEdit 】
- Sys节点相关
- pdf文档解析的研究
- 安静的力量:内向者的静争力
- 生成不重复随机数