zoukankan      html  css  js  c++  java
  • [kmp+dp] hdu 4628 Pieces

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4622

    Reincarnation

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
    Total Submission(s): 2096    Accepted Submission(s): 715


    Problem Description
    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.
     

    Input
    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.
     

    Output
    For each test cases,for each query,print the answer in one line.
     

    Sample Input
    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
     

    Sample Output
    3 1 7 5 8 1 3 8 5 1
    Hint
    I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
     

    Source
     

    Recommend
    zhuyuanchen520   |   We have carefully selected several similar problems for you:  5061 5060 5059 5058 5057 


    题目意思:

    给一个字符串,对每一个字符串,有非常多询问,询问给定区间不同子串的个数。

    解题思路:

    kmp+dp

    普通的dp转移肯定超时。

    sa[i][j]:表示以第j个字符開始可以往前最多的字符个数(如果为s个),要求满足【j-s+1,j】在【i,j-1】字符串区间出现。

    这样要统计j開始的往前的情况,能够把字符串倒过来,把j作为第一个,然后1作为最后一个,求一遍next.然后更新sa[i][j] (i<j)

    求出sa[i][j]后,就能够直接转移dp[i][j]=dp[i][j-1]+i-j+1-sa[i][j] //把第j个字符加上后,对整个子串个数的影响。减去在前面已经出现的。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    
    #define Maxn 2200
    
    char sa1[Maxn];
    char sa2[Maxn];
    int next[Maxn];
    int n,nn;
    int sa[Maxn][Maxn],dp[Maxn][Maxn];
    
    void getnext()
    {
        int j=0;
        next[1]=0;
    
        for(int i=2;i<=nn;i++)
        {
            while(j>0&&sa1[j+1]-sa1[i])
                j=next[j];
            if(sa1[j+1]==sa1[i])
                j++;
            next[i]=j;
        }
        return ;
    }
    int main()
    {
        int t;
    
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",sa1+1);
            n=strlen(sa1+1);
            for(int i=1;i<=n;i++)
                sa2[i]=sa1[n+1-i];
            
            for(int i=1;i<=n;i++)
            {
               
                for(int j=i;j<=n;j++)
                    sa1[j-i+1]=sa2[j];
                nn=n-i+1;
                getnext();
                sa[n+1-i-1][n+1-i]=next[2];
    
                for(int j=i+2;j<=n;j++)
                    sa[n+1-i-(j-i)][n+1-i]=max(next[j-i+1],sa[n+1-i-(j-i)+1][n+1-i]);
            }
       
    
            for(int i=1;i<=n;i++)
            {
                dp[i][i]=1;
                for(int j=i+1;j<=n;j++)
                    dp[i][j]=dp[i][j-1]+(j-i+1)-sa[i][j];
          
               
            }
            int q;
    
            scanf("%d",&q);
            while(q--)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                printf("%d
    ",dp[a][b]);
            }
        }
        return 0;
    }



  • 相关阅读:
    java开学第一周测试自我感想
    暑假第八周进度报告
    暑假第七周进度报告
    暑假第六周进度报告
    暑假第五周进度报告
    暑假第四周进度报告
    暑假第三周进度报告
    暑假第二周进度报告
    《大道至简》读后感
    暑假第一周进度报告
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4269743.html
Copyright © 2011-2022 走看看