zoukankan      html  css  js  c++  java
  • CF835D Solution

    题目链接

    题解

    因为长度为\(i\)\(k\)阶回文串一定由2个长度为\(\lfloor\frac{i}{2} \rfloor\)\(k-1\)阶回文串组成,可以想到区间dp。

    状态:\(dp[l][r]\)表示回文子串\([l,r]\)的阶数(若不是回文串为\(0\))。

    转移方程:

    \[dp[l][r]=dp[l][(l+r-1)/2]+1\quad (1\le l<r\le n,r-l\ge 2,dp[l+1][r-1]>0,s_l=s_r)\\ dp[l][l]=1\quad (1\le l\le n)\\ dp[l][l+1]=2\quad (1\le l<n,s_l=s_{l+1}) \]

    易得,当区间\([l+1,r-1]\)为回文子串且\(s_l=s_r\)时,区间\([l,r]\)为回文子串,而其阶数等于左/右半部分阶数\(+1\)。长度为\(1/2\)的回文子串需特殊处理。

    答案:设\(sum_i\)表示\(i\)阶回文子串的个数,\(sum_i=\sum dp[l][r]\quad (dp[l][r]=i)\)。因为\(k\)阶回文子串同时为\([1,k-1]\)阶回文子串,需对\(sum\)数组求后缀和。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5010;
    char s[N];
    int dp[N][N],sum[N];
    int main()
    {
    	scanf("%s",s+1);
    	int n=strlen(s+1);
    	for(int i=1;i<=n;i++)
    	{
    		if(s[i]==s[i+1]) dp[i][i+1]=2,sum[2]++;
    		dp[i][i]=1; sum[1]++;
    	}
    	for(int i=2;i<=n;i++)
    	{
    		for(int l=1;l+i<=n;l++)
    		{
    			int r=l+i;
    			if(!dp[l+1][r-1] || s[l]!=s[r]) continue;
    			dp[l][r]=dp[l][(l+r-1)/2]+1; sum[dp[l][r]]++;
    		}
    	}
    	for(int i=n;i>=1;i--) sum[i]+=sum[i+1];
    	for(int i=1;i<=n;i++) printf("%d ",sum[i]);
    	return 0;
    }
    
  • 相关阅读:
    Redis(二) 扩展
    Redis(一)基础
    Java垃圾回收机制 入门
    freeregex-0.01 使用文档
    上传文件到阿里云linux服务器
    jQuery代码解释(基本语法)
    JQuery中使用FormData异步提交数据和提交文件
    jQuery获取data-*属性值
    jquery 中 $.map 的使用方法
    mysql创建表时反引号的作用
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14374999.html
Copyright © 2011-2022 走看看