Codeforces Round #427 (Div. 2) D.Palindromic characteristics

題目鏈接
題意是這樣的:定義了一種k階迴文串,1-階是普通的迴文串,k-階迴文串的前半串和後半串必須是相等的(不是迴文,例如abcabc,如果長度奇數中間的不管他)然後其前半串必須是k-1階迴文串,後半串必須是k-1階迴文串。
然後給一個串,問這個串有多少子串是i階迴文串(i從1到n,依次輸出)
分析一下可以看出如果一個串是k階迴文串,那麼他必然是k-1階迴文串,於是我們可以枚舉該串的子串記錄他最大能到達的階數,然後通過區間dp轉移一下。由於階數的每次增長都必然伴隨着串長的加倍,所以k最大隻有logn個。直接區間dp複雜度o(n² logn)

#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define  LONG long long
const int   INF=0x3f3f3f3f;
const LONG  MOD=1e9+ 7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)+1
#define root 1, n , 1
char str[5010] ;
int ans [5010] ;
int dp[5010][5010] ;
int match[5010][5010] ;
int main()
{
    while(~scanf("%s",str+1))
    {
        clr0(ans ) ;
        clr0(dp) ;
        str[0] = '#' ;
        int len = strlen(str ) ;

        len --;
        for(int i = 1 ; i <= len+5 ; ++i)
            dp[i][i-1] = 1 ;
        for(int i = 2 ; i <= len+5 ; ++i)
            dp[i][i-2] = 1 ;
            //
for (int i=1;i<=len;i++)
     match[i][i]=1;

     for (int l=1;l<=len;l++)
      for (int i=1;i+l<=len;i++)
        if  ( str[i] == str[i+l])
          {
              if (l==1)
              match[i][i+l] = 1;
              else
              match[i][i+l] |= match[i+1][i+l-1];
          }
//
        for(int l = 1 ; l <= len ; ++ l)
        {
            for(int i = 1 ; i <= len ; ++ i)
            {
                int j = i + l -1;
                if( j > len ) break ;
                if(str[i] == str[j]) if(dp[i+1][j-1]) dp[i][j] = 1;
                int mid = l/2  ;
                if(l <= 1) continue ;
                if(l&1)
                {
                    if(dp[i][i+mid-1] == dp[i+mid+1][j] )
                    {
                        if( match[i][j] )
                        {
                            if(str[i] == str[j]) dp[i][j] = max(dp[i][j] , dp[i][i+mid-1] + 1) ;
                        }
                    }
                }
                else
                {
                    if(dp[i][i+mid-1] == dp[i+mid][j])
                    {
                            if(str[i] == str[j] && match[i][j] )
                                dp[i][j] = max(dp[i][j] , dp[i][i+mid-1] + 1 );
                    }

                }
            }
        }
        for(int i = 1 ;i<= len ; ++ i)
        {
            for(int j = i ; j<= len ; ++ j)
                for(int k = 1 ;k<= dp[i][j] ; ++ k)
                    ans[k] ++ ;
        }
        for(int i = 1;i <len ; ++ i)printf("%d ",ans[i]) ;printf("%d\n",ans[len]) ;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章