hdu4691 Front compression(后缀数组)
Front compression
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 1339 Accepted Submission(s): 496
The size of the input is 43 bytes, while the size of the compressed output is
40. Here, every space and newline is also counted as 1 byte.
Given the input, each line of which is a substring of a long string, what are sizes of it and corresponding compressed output?
The first line of each test case is a long string S made up of lowercase letters, whose length doesn't exceed 100,000. The second line contains a integer 1 ≤ N ≤ 100,000, which is the number of lines in the input. Each of the following N lines contains two
integers 0 ≤ A < B ≤ length(S), indicating that that line of the input is substring [A, B) of S.
frcode
2
0 6
0 6
unitedstatesofamerica
3
0 6
0 12
0 21
myxophytamyxopodnabnabbednabbingnabit
6
0 9
9 16
16 19
19 25
25 32
32 37
14 12
42 31
43 40
pid=5061">5061
5060 5059
pid=5058">
5058
pid=5057">
5057
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define maxn 100010
using namespace std;
char s[maxn];
int n,k,q;
int rank[maxn],sa[maxn],tmp[maxn],lcp[maxn];//lcp:0-n-1
bool cmp(int x,int y){
if(rank[x]!=rank[y]) return rank[x]<rank[y];
int sx=x+k<=n ? rank[x+k]:-1;
int sy=y+k<=n ? rank[y+k]:-1;
return sx<sy;
}
void build_sa(){
n=strlen(s);
for(int i=0;i<=n;i++){
sa[i]=i;
rank[i]=i<n ? s[i]:-1;
}
for(k=1;k<=n;k<<=1){
sort(sa,sa+n+1,cmp);
tmp[sa[0]]=0;
for(int i=1;i<=n;i++){
tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i]) ? 1:0);
}
for(int i=0;i<=n;i++) rank[i]=tmp[i];
}
}
void build_lcp(){
n=strlen(s);
//for(int i=0;i<=n;i++) rank[sa[i]]=i;
int h=0;
lcp[0]=0;
for(int i=0;i<n;i++){
int j=sa[rank[i]-1];
if(h>0) h--;
for(;j+h<n&&i+h<n;h++){
if(s[j+h]!=s[i+h]) break;
}
lcp[rank[i]-1]=h;
}
}
int dp[20][maxn],mm[maxn];
void init_RMQ(int n){
mm[0]=-1;
for(int i=1;i<=n;i++){//长度1-n
mm[i]=(i&(i-1)) ? mm[i-1]:mm[i-1]+1;
}
for(int i=0;i<n;i++) dp[0][i]=lcp[i];
for(int i=1;i<=mm[n];i++){
for(int j=0;j+(1<<i)-1<n;j++){
dp[i][j]=min(dp[i-1][j],dp[i-1][j+(1<<i>>1)]);
}
}
}
int RMQ(int x,int y){//[x,y-1]
if(x==y) return n-x;
x=rank[x],y=rank[y];
if(x>y) swap(x,y);
y--;
int l=mm[y-x+1];
return min(dp[l][x],dp[l][y-(1<<l)+1]);
}
void read(){
scanf("%d",&q);
ll sum1=0,sum2=0;
int pl=-1,pr=-1,l,r;
for(int i=0;i<q;i++){
scanf("%d%d",&l,&r);
sum1+=(r-l+1);
if(pl==-1){
sum2+=r-l+1;
}else{
int LCP=RMQ(pl,l);
int ans=min(LCP,min(r-l,pr-pl));
sum2+=(r-l-ans);
if(ans==0) sum2+=1;
else sum2+=(int)log10(ans*1.0)+1;
}
pl=l,pr=r;
}
printf("%I64d %I64d\n",sum1,sum2+2*q);
}
int main(){
while(~scanf("%s",s)){
build_sa();
build_lcp();
init_RMQ(n);
read();
}
return 0;
}
板子2:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define maxn 100010
using namespace std;
char s[maxn];
int c[maxn],wa[maxn],wb[maxn],r[maxn];//求SA数组须要的中间变量,不须要赋值
//待排序的字符串放在s数组中,从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的全部s[i]都大于0,r[n-1]=0
//函数结束以后结果放在sa数组中
int n,sa[maxn],lcp[maxn],rank[maxn];
bool cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void build_sa(int n,int m){//数组长度,最大数字
for(int i=0;i<=n;i++) r[i]=i<n ? s[i]:0;
n++;
int i,j,p,*x=wa,*y=wb;
//第一轮基数排序。假设s的最大值非常大,可改为高速排序
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=r[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(j=1;j<=n;j<<=1){
p=0;
//直接利用sa数组排序第二keyword
for(i=n-j;i<n;i++) y[p++]=i;//后面的j个数第二keyword为空的最小
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
//这样数组y保存的就是依照第二keyword排序的结果
//基数排序第一keyword
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
//依据sa和x数组计算新的x数组
swap(x,y);
p=1,x[sa[0]]=0;
for(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;
}
}
void build_lcp(int n){
int i,j,k=0;
for(i=0;i<=n;i++) rank[sa[i]]=i;
lcp[0]=0;
for(i=0;i<n;i++){
j=sa[rank[i]-1];
if(k) k--;
while(s[i+k]==s[j+k]) k++;
lcp[rank[i]-1]=k;
}
}
int dp[20][maxn],mm[maxn];
void init_RMQ(int n){
mm[0]=-1;
for(int i=1;i<=n;i++){
mm[i]=(i&(i-1)) ? mm[i-1]:mm[i-1]+1;
}
for(int i=0;i<n;i++) dp[0][i]=lcp[i];
for(int i=1;i<=mm[n];i++){
for(int j=0;j+(1<<i)-1<n;j++){
dp[i][j]=min(dp[i-1][j],dp[i-1][j+(1<<i>>1)]);
}
}
}
int RMQ(int x,int y){
if(x==y) return n-x;
x=rank[x],y=rank[y];
if(x>y) swap(x,y);
y--;
int l=mm[y-x+1];
return min(dp[l][x],dp[l][y-(1<<l)+1]);
}
int q;
void read(){
scanf("%d",&q);
ll sum1=0,sum2=0;
int pl=-1,pr=-1,l,r;
for(int i=0;i<q;i++){
scanf("%d%d",&l,&r);
sum1+=(r-l+1);
if(pl==-1){
sum2+=r-l+1;
}else{
int LCP=RMQ(pl,l);
//cout<<i<<":"<<LCP<<endl;
int ans=min(LCP,min(r-l,pr-pl));
//cout<<i<<":"<<ans<<endl;
sum2+=(r-l-ans);
if(ans==0) sum2+=1;
else sum2+=(int)log10(ans*1.0)+1;
}
pl=l,pr=r;
}
printf("%I64d %I64d\n",sum1,sum2+2*q);
}
int main(){
while(~scanf("%s",s)){
n=strlen(s);
build_sa(n,128);
build_lcp(n);
/*for(int i=0;i<n;i++){
cout<<i<<" "<<sa[i]<<" "<<lcp[i]<<endl;
}*/
init_RMQ(n);
read();
}
return 0;
}
hdu4691 Front compression(后缀数组)的更多相关文章
- HDU-4691 Front compression 后缀数组
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4691 后缀数组模板题,求出Height数组后,对Height做RMQ,然后直接统计就可以了... // ...
- hdu4691 Front compression ——暴力 || 后缀数组
link:http://acm.hdu.edu.cn/showproblem.php?pid=4691 暴力,数据明显太水了吧,n=10^5, O(n^2)的复杂度哎喂.想让大家暴力写直接让n=100 ...
- hdu 4691 Front compression (后缀数组)
hdu 4691 Front compression 题意:很简单的,就是给一个字符串,然后给出n个区间,输出两个ans,一个是所有区间的长度和,另一个是区间i跟区间i-1的最长公共前缀的长度的数值的 ...
- HDU 4691 Front compression (2013多校9 1006题 后缀数组)
Front compression Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Othe ...
- HDU 4691 Front compression(后缀数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4691 题意:给出Input,求出Compressed output.输出各用多少字节. 思路:求后缀数 ...
- hdu4691(后缀数组)
算是后缀数组的入门题吧. 思路无比简单,要是直接套模板的话应该很容易秒掉. 关于后缀数组看高中神犇的论文就可以学会了 算法合集之<后缀数组——处理字符串的有力工具> 话说这题暴力是可以过了 ...
- bzoj 3172 单词 ac自动机|后缀数组
题目大意: 给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖 这里ac自动机和后缀数组都可以做 当然后缀数组很容易就解决,但是相对时间消耗高 这里就只讲ac自动机了 将每个 ...
- HDU5853 Jong Hyok and String(二分 + 后缀数组)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5853 Description Jong Hyok loves strings. One da ...
- Ural1297 Palindrome(后缀数组)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12406 [题意] 求最长回文子串. [思路] 将字符串 ...
随机推荐
- 查看Linux 服务器是 32位还是64位的
查看Linux 服务器是 32位还是64位的 getconf LONG_BIT 返回 64 代表就是 64位的: 返回 32 代表就是 32位的:
- 【BZOJ4176】Lucas的数论-杜教筛
求$$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}f(ij)$$,其中$f(x)$表示$x$的约数个数,$0\leq n\leq 10^9$,答案膜$10^9+ ...
- BZOJ 1190 [HNOI2007]梦幻岛宝珠(背包)
1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1385 Solved: 798[Submit][Stat ...
- C语言实现简化的正则表达式
语法: 正则表达式和待匹配字符串都是一行 "^" 标记正则表达式的开始 "$" 标记正则表达式的结束 "*" 匹配前面的子表达式零次或多次 ...
- MySQL数据类型及后面小括号的意义
1,数值类型 1.1数值类型的种类 标准 SQL 中的数值类型,包括严格数值类型(INTEGER.SMALLINT.DECIMAL.NUMERIC),以及近似数值数据类型(FLOAT.REAL.DOU ...
- 【转】 C#学习笔记14——Trace、Debug和TraceSource的使用以及日志设计
[转] C#学习笔记14——Trace.Debug和TraceSource的使用以及日志设计 Trace.Debug和TraceSource的使用以及日志设计 .NET Framework 命名空 ...
- 洛谷 P3662 [USACO17FEB]Why Did the Cow Cross the Road II S
P3662 [USACO17FEB]Why Did the Cow Cross the Road II S 题目描述 The long road through Farmer John's farm ...
- 洛谷 P3147 [USACO16OPEN]262144
P3147 [USACO16OPEN]262144 题目描述 Bessie likes downloading games to play on her cell phone, even though ...
- 在VS2013中配置QT5 win7_64
转自 在VS2013中配置QT5 win7_64 环境: win x64 + vs2013+QT5+vs_addin 下面示例正确配置QT以及VS2013 + QT Addin开发环境: 下载VS20 ...
- ftoa浮点型转换成字符串
#include <stdio.h> bool ftos(float num,char *s,int n) { int temp; float t=num; int pn=0; b ...