Reincarnation

40 篇文章 0 订阅
28 篇文章 9 订阅

题目描述

Now you are back,and have a task to do: 
Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s. 
And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.

输入描述:

The first line contains integer T(1<=T<=5), denote the number of the test cases.
       
 For each test cases,the first line contains a string s(1 <= length of s <= 2000).
       
 Denote the length of s by n.
       
 The second line contains an integer Q(1 <= Q <= 10000),denote the number of queries.
       
 Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n), denote a query.

输出描述:

For each test cases,for each query,print the answer in one line.
示例1

输入

2
bbaba
5
3 4
2 2
2 5
2 4
1 4
baaba
5
3 3
3 4
1 4
3 5
5 5

输出

3
1
7
5
8
1
3
8
5
1
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include <stdlib.h>
#define ll __int64
using namespace std ;
 
const int maxn = 1111111 ;
 
ll f[maxn] , g[maxn] ;
int wa[maxn] , wb[maxn] , wv[maxn] , ws[maxn] , pos[maxn] ;
struct suf
{
    int sa[maxn] , hei[maxn] , rank[maxn] ;
 
    int cmp ( int *r , int i , int j , int l )
    {
        return r[i] == r[j] && r[i+l] == r[j+l] ;
    }
 
    void da ( int *r , int n , int m )
    {
        int *x = wa , *y = wb , *t ;
        int i , j , p ;
        for ( i = 0 ; i < m ; i ++ ) ws[i] = 0 ;
        for ( i = 0 ; i < n ; i ++ ) ws[x[i]=r[i]] ++ ;
        for ( i = 1 ; i < m ; i ++ ) ws[i] += ws[i-1] ;
        for ( i = n - 1 ; i >= 0 ; i -- ) sa[--ws[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 < m ; i ++ ) ws[i] = 0 ;
            for ( i = 0 ; i < n ; i ++ ) ws[x[i]] ++ ;
            for ( i = 1 ; i < m ; i ++ ) ws[i] += ws[i-1] ;
            for ( i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[y[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 ++ ;
        }
        int k = 0 ;
        for ( i = 1 ; i < n ; i ++ ) rank[sa[i]] = i ;
        for ( i = 0 ; i < n - 1 ; hei[rank[i++]] = k )
            for ( k ? k -- : 0 , j = sa[rank[i]-1] ; r[i+k] == r[j+k] ; k ++ ) ;
    }
 
    int solve ( int n )
    {
        int ans = 0 , i ;
        for ( i = 1 ; i <= n ; i ++ )
            ans += n - sa[i] - hei[i] ;
        return ans ;
    }
 
} arr ;
 
int s1[maxn] , dp[20][2222] ;
void rmq ( int n )
{
    int i , j ;
    f[0] = 1 ;
    for ( i = 1 ; i <= 15 ; i ++ )
        f[i] = f[i-1] * 2 ;
    g[0] = -1 ;
    for ( i = 1 ; i < 2222 ; i ++ )
        g[i] = g[i>>1] + 1 ;
    for ( i = 1 ; f[i] <= n ; i ++ )
        for ( j = 1 ; j + f[i] - 1 <= n ; j ++ )
            dp[i][j] = min ( dp[i-1][j] , dp[i-1][j+f[i-1]] ) ;
}
int query ( int l , int r )
{
    if ( l == r ) return dp[0][l] ;
    if ( l > r ) swap ( l , r ) ;
    int i , j , k ;
    k = g[r-l+1] ;
    return min ( dp[k][l] , dp[k][r-f[k]+1] ) ;
}
char s[maxn] ;
int num[maxn] ;
int main ()
{
    int n , k , i , l , r ;
    int cas ;
    scanf ( "%d" , &cas ) ;
    while ( cas -- )
    {
        int q ;
        scanf ( "%s" , s ) ;
        int len = strlen ( s ) ;
        for ( i = 0 ; i < len ; i ++ ) s1[i] = s[i] ;
        s1[len] = 0 ;
        arr.da ( s1 , len + 1 , 555 ) ;
        for ( i = 1 ; i <= len ; i ++ )
            dp[0][i] = arr.hei[i] ;
        rmq ( len ) ;
        n = len ;
        scanf ( "%d" , &q ) ;
        while ( q -- )
        {
            scanf ( "%d%d" , &l , &r ) ;
            int ans = ( r - l + 1 ) * ( r - l + 2) / 2 ;
            for ( i = 0 ; i <= n ; i ++ ) pos[i] = -1 ;
            for ( i = l ; i <= r ; i ++ )
                pos[arr.rank[i-1]] = i - 1 ;
            int last = -1 , d = 0 ;
            for ( i = 1 ; i <= n ; i ++ )
            {
                if ( pos[i] != -1 )
                {
                    if ( last != -1 )
                    {
                        int t = query ( arr.rank[last] + 1 , arr.rank[pos[i]] ) ;
                        d = min ( d , t ) ;
                        d = max ( d , min ( t , r - last ) ) ;
                        ans -= min ( d , r - pos[i] );
                    }
                    last = pos[i] ;
                }
            }
            printf ( "%d\n" , ans ) ;
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值