zoukankan      html  css  js  c++  java
  • CodeForces-245H:Queries for Number of Palindromes(3-14:区间DP||回文串)

    Times:5000ms;

    Memory limit:262144 kB

    给定字符串S(|S|<=5000),下标由1开始。然后Q个问题(Q<=1e6),对于每个问题,给定L,R,回答区间[L,R]里有多少个回文串。

    请想出两种或者以上的方法。

    ------------------------分界线--------------------------

     方法1:区间DP。

              容斥一下,dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+ok[i][j],(ok表示是否是个回文串)。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=5010;
    int dp[maxn][maxn],ok[maxn][maxn],N,Q;
    char c[maxn];
    void DP()
    {
        for(int i=N;i>=1;i--)
          for(int j=i;j<=N;j++){
             if(j-i==0) ok[i][j]=1,dp[i][j]=1;
             else if(j-i==1) dp[i][j]=ok[i][j]=dp[i][i]+dp[j][j]+(c[i]==c[j]?1:0);
             else {
                ok[i][j]=ok[i+1][j-1]&(c[i]==c[j]);
                dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+ok[i][j];
             }
        }
    }
    int main()
    {
        scanf("%s",c+1);
        N=strlen(c+1);
        DP();
        scanf("%d",&Q);
        while(Q--){
            int x,y; scanf("%d%d",&x,&y);
            printf("%d
    ",dp[x][y]);
        }
        return 0;
    }

    方法2: 

            马拉车:每个为起点,然后预处理得到每个为起点的回文串个数前缀和。 为了训练,就先不给带代码了。

    方法3:回文树,这个我还不会。

    方法4:暴力,开始我以为暴力得到回文串,然后差分得到前缀和,但是前缀和涉及到了交叉问题可能会导致出错。所以,目前还不行。(不过别人说可以,那再想想)

     

  • 相关阅读:
    利用opengl画一个水波的曲面
    Eclipse 使用OpenGL
    Javascript学习过程(二)
    Workflow Learing
    YAWL设计实例
    YAWL使用方法
    ImageJ二次开发学习纪录之初步体会
    [LeetCode 660] Remove 9
    [LeetCode 1542] Find Longest Awesome Substring
    [LeetCode 879] Profitable Schemes
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8570100.html
Copyright © 2011-2022 走看看