HDU-4691 Front compression 后缀数组
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4691
后缀数组模板题,求出Height数组后,对Height做RMQ,然后直接统计就可以了。。。
//STATUS:C++_AC_828MS_11284KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,102400000")
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef __int64 LL;
typedef unsigned __int64 ULL;
//const
const int N=;
const int INF=0x3f3f3f3f;
const int MOD=,STA=;
const LL LNF=1LL<<;
const double EPS=1e-;
const double OO=1e15;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End char s[N];
int d[N][];
int num[N];
int sa[N],t1[N],t2[N],c[N],rank[N],height[N];
int n,m; void build_sa(int s[],int n,int m)
{
int i,k,p,*x=t1,*y=t2;
//第一轮基数排序
for(i=;i<m;i++)c[i]=;
for(i=;i<n;i++)c[x[i]=s[i]]++;
for(i=;i<m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[i]]]=i;
for(k=;k<=n;k<<=){
p=;
//直接利用sa数组排序第二关键字
for(i=n-k;i<n;i++)y[p++]=i;
for(i=;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
//基数排序第一关键字
for(i=;i<m;i++)c[i]=;
for(i=;i<n;i++)c[x[y[i]]]++;
for(i=;i<m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[y[i]]]]=y[i];
//根据sa和x数组计算新的x数组
swap(x,y);
p=;x[sa[]]=;
for(i=;i<n;i++)
x[sa[i]]=y[sa[i-]]==y[sa[i]] && y[sa[i-]+k]==y[sa[i]+k]?p-:p++;
if(p>=n)break; //已经排好序,直接退出
m=p; //下次基数排序的最大值
}
} void getHeight(int s[],int n)
{
int i,j,k=;
for(i=;i<=n;i++)rank[sa[i]]=i;
for(i=;i<n;i++){
if(k)k--;
j=sa[rank[i]-];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
} void rmq_init(int a[])
{
int i,j;
for(i=;i<=n;i++)d[i][]=a[i];
for(j=;(<<j)<=n;j++){
for(i=;i+(<<j)-<=n;i++){
d[i][j]=Min(d[i][j-],d[i+(<<(j-))][j-]);
}
}
} int rmq(int l,int r)
{
int k=;
while((<<(k+))<=r-l+)k++;
return Min(d[l][k],d[r-(<<k)+][k]);
} int lcp(int a,int b)
{
if(a==b)return n-a; //a和b为同一后缀,直接输出,字串串长度为n
int ra=rank[a],rb=rank[b];
if(ra>rb)swap(ra,rb);
return rmq(ra+,rb);
} int w[N]; int main(){
// freopen("in.txt","r",stdin);
int i,j,k,Q,a,b,la,lb;
LL ans1,ans2,t;
w[]=;
for(i=k=;i<N;i=j,k++)
for(j=i*;i<j && i<N;i++)w[i]=k;
while(~scanf("%s",s))
{
n=strlen(s);
for(i=;i<n;i++)
num[i]=s[i]-'a'+;
num[n]=;m=;
build_sa(num,n+,m);
getHeight(num,n);
rmq_init(height); scanf("%d",&Q);
ans1=(LL)Q,ans2=(LL)*Q;
scanf("%d%d",&la,&lb);
ans1+=(LL)lb-la;ans2+=(LL)lb-la+;
while(--Q){
scanf("%d%d",&a,&b);
ans1+=(LL)b-a;
t=(LL)Min(lcp(la,a),lb-la,b-a);
ans2+=(LL)b-a-t+w[t];
// printf(" %I64d %d %d %d\n",t,lcp(la,a),lb-la,b-a);
la=a;lb=b;
} printf("%I64d %I64d\n",ans1,ans2); }
return ;
}
HDU-4691 Front compression 后缀数组的更多相关文章
- hdu 4691 Front compression (后缀数组)
hdu 4691 Front compression 题意:很简单的,就是给一个字符串,然后给出n个区间,输出两个ans,一个是所有区间的长度和,另一个是区间i跟区间i-1的最长公共前缀的长度的数值的 ...
- HDU 4691 Front compression(后缀数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4691 题意:给出Input,求出Compressed output.输出各用多少字节. 思路:求后缀数 ...
- HDU 4691 Front compression (2013多校9 1006题 后缀数组)
Front compression Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Othe ...
- hdu4691 Front compression(后缀数组)
Front compression Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) ...
- HDU 4691 正解后缀数组(暴力也能过)
本来是个后缀数组,考察算法的中级题目,暴力居然也可以水过,就看你跳不跳坑了(c++和G++返回结果就很不一样,关键看编译器) 丝毫不差的代码,就看运气如何了.唯一差别c++还是G++,但正解是后缀数组 ...
- hdu 4691 Front compression
暴力水过,剪一下枝= =果断是数据水了 #include<cstdio> #include<cstring> #include<algorithm> #define ...
- 【HDOJ】4691 Front compression
后缀数组基础题目,dc3解. /* 4691 */ #include <iostream> #include <sstream> #include <string> ...
- hdu 5442 Favorite Donut 后缀数组
Favorite Donut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...
- hdu 4622 Reincarnation(后缀数组)
hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...
随机推荐
- Java 程序检查远程服务器状态
通常我们以命令的方式判断远程服务器是否正常运行有两种方式,ping 或 telnet 一个远程端口.假设我们要检查的远程服务器都是 Linux 系统. 从 JDK 1.5 以后, InetAddres ...
- hdu 3400 Line belt 三分法
思路:要求最短时间从A到D,则走的路线一定是AB上的一段,CD上的一段,AB与CD之间的一段. 那么可以先三分得到AB上的一个点,在由这个点三分CD!! 代码如下: #include<iostr ...
- linux 使用kill命令杀死进程的几个办法
常规篇: 首先,用ps查看进程,方法如下: $ ps -ef ……smx 1822 1 0 11:38 ? 00:00:49 gnome-terminalsmx ...
- 使用Data Annotations进行手动数据验证
Data Annotations是在Asp.Net中用于表单验证的 它通过Attribute直接标记字段的有效性,简单且直观.在非Asp.Net程序中(如控制台程序),我们也可以使用Data Anno ...
- vmware tools安装程序无法继续,Microsoft Runtime DLL安装程序未能完成安装。的解决方法
vmware tools安装程序无法继续,Microsoft Runtime DLL安装程序未能完成安装.的解决方法_华英雄_新浪博客 http://blog.sina.com.cn/s/blog_5 ...
- 107. Binary Tree Level Order Traversal II
题目: Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from ...
- Android EditView 阻止软键盘自动弹出
最近再做一个查询内的小应用,界面最上面是一个EditText查询框,进行Activity后,总会弹起软键盘.这样就挡住了查询框下面的其他查询条件 控件,感觉很不友好.所以现在要做的就是在进入Activ ...
- 安装Ubuntu双系统系列——安装Ubuntu
一.将Ubuntu系统烧进U盘 1.打开老毛桃,选择“U盘启动” -> "ISO模式":选择ISO文件,我这里安装的是Ubuntu12.04-64bit,你可以在网上下载一个 ...
- Ubuntu 12.04搭建Andorid编译环境
1.安装JDK,Android 5.0开始,开始使用OpenJDK 1.7,4.4等低版本是Oracke JDK1.6 install java environment // install open ...
- php修改排序,上移下移
php修改排序,上移下移 /** $UpDown //移动方向,up或down $table //表名 $id //当前移动的ID $id_col //ID字段的名称 $ ...