#include<iostream>
#include<cstring>
#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int MAX = 200050;
int sa[MAX], rank[MAX], height[MAX];
int wa[MAX], wb[MAX], wv[MAX], wd[MAX];
char str[MAX];
int Max[20][MAX];
int Min[20][MAX];
int idx[MAX];
void initRMQ(int n) {
idx[0] = -1;
for(int i = 1; i <= n ; i ++) {
idx[i] = (i&(i-1)) ? idx[i-1] : idx[i-1] + 1;
Min[0][i] = Max[0][i] = height[i];
}
for(int i = 1; i <= idx[n] ; i ++) {
int limit = n + 1 - (1<<i);
for(int j = 1; j <= limit ; j ++) {
Min[i][j] = min(Min[i-1][j] , Min[i-1][j+(1<<i>>1)]);
Max[i][j] = max(Max[i-1][j] , Max[i-1][j+(1<<i>>1)]);
}
}
}
int getval(int a,int b) {
if(a > b) swap(a , b);
if(a != b) b--;
a ++;
b ++;
int t = idx[b-a+1];
b -= (1<<t) - 1;
return min(Min[t][a] , Min[t][b]);
}
int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int *r, int n, int m) // 倍增算法0(nlgn)。
{
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 = 1; i <= n; i ++) rank[sa[i]] = i;
for(i = 0; i < n; height[rank[i ++]] = k)
{
for(k ? k -- : 0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k ++);
}
}
void debug(){
for(int i = 0 ; i < strlen(str) ; i ++){
printf("%d " , rank[i]);
}
printf("\n");
for(int i = 1 ; i <= strlen(str) ; i ++){
printf("%d " , height[i]);
}
printf("\n");
return ;
}
int f(int t){
int ret = 0;
while(t){
t /= 10;
ret ++;
}
return ret;
}
int main()
{
int i, k, l1, num[MAX] ,a , b , n ,pa , pb,up,down,m;
while(~scanf("%s", str)){
__int64 ret = 1;
__int64 ret1 = 0;
l1 = strlen(str);
for(k = i = 0; i < l1; i ++)
{
num[k ++] = str[i] - 'a' + 2;
}
num[k ++] = 1; // 相当于论文中的'$'分隔符。
int n = l1;
da(num, n + 1, 30);
calHeight(num, n);
//debug();
scanf("%d" , &m);
initRMQ(n);
int temp;
for(int i = 0 ; i < m ; i ++){
scanf("%d%d" , &a , &b);
ret1 += (b - a + 1);
if(i == 0) {
ret += (b - a);
}
else{
up = rank[a];
down = rank[pa];
if(up == down){
temp = min(pb - pa , b - a);
}
else{
temp = getval(up , down);
temp = min(temp , b - a);
temp = min(temp , pb - pa);
}
int sum;
if(temp == 0) sum = 1;
else sum = f(temp);
temp = b - a - temp;
ret += temp;//
ret += sum;
}
pa = a;
pb = b;
}
ret += 2 * m;
printf("%I64d " , ret1);
printf("%I64d\n" , ret);
}
return 0;
}
/*
aabaaaab
100
0 3
5 6
*/
hdu 4691 Front compression (后缀数组)
最新推荐文章于 2019-04-01 18:43:27 发布