UVA1633
一个长的回文串都可以由短的回文串拓展而来,只要短的回文在左右两端增加相同的字符即可。因此,在考虑长度为NNN的01串时,只要在从长度为1向NNN拓展的过程中,保证后KKK个字符不是回文串即可。
定义
dp[i][j]dp[i][j]dp[i][j]为考虑长度为i的串的后KKK个字符组成的子串为jjj时的合法字符串的数量。IsPalindrome[i][j]IsPalindrome[i][j]IsPalindrome[i][j]为长度为iii的字符串jjj是否为回文串。由于K≤10K\leq 10K≤10,小于intintint的32为并且为01串,可以用一个intintint来保存字符串jjj,进行状态压缩。

求IsPalindrome

初始化
IsPalindrome[1][0]=dp[1][1]=trueIsPalindrome[2][0]=dp[2][3]=trueIsPalindrome[1][0]=dp[1][1]=true\\IsPalindrome[2][0]=dp[2][3]=trueIsPalindrome[1][0]=dp[1][1]=trueIsPalindrome[2][0]=dp[2][3]=true即0,1,00,11为回文串。
转移方程
IsPalindrome[i][j]=IsPalindrome[i−2][j去掉第一个字符和最后一个字符形成的子串]&&(j的第一个字符==j的最后一个字符)IsPalindrome[i][j]=IsPalindrome[i-2][j去掉第一个字符和最后一个字符形成的子串]\\\&\&\\(j的第一个字符==j的最后一个字符)IsPalindrome[i][j]=IsPalindrome[i−2][j去掉第一个字符和最后一个字符形成的子串]&&(j的第一个字符==j的最后一个字符)典型的中心拓展法,一个回文串如果左右各增加一个相同的字符,则形成的新字符串仍然是回文串。

求dp

初始化
dp[0][0]=1,其他元素=0dp[0][0]=1,其他元素=0dp[0][0]=1,其他元素=0即空串绝对合法且种类唯一。
转移方程

int getState(int State, int Last) {//如果State的长度大于等于K,则去掉最左边if (State >= 1 << K - 1) {State -= 1 << K - 1;}//往右边拓展一格return State << 1 | Last;
}
for (int i = 1; i <= N; ++i) {for (int j = 0; j <= (1 << K) - 1; ++j) {//如果前一状态的合法数为0,就没必要继续了if (dp[i - 1][j] == 0) {continue;}//枚举最右边添加0还是1for (int x = 0; x <= 1; ++x) {//将j往右拓展一格int&& CurState = getState(j, x);///如果i的后K个字符往右移动一位组成了回文串,就跳过if (i >= K && IsPalindrome[K][CurState]) {continue;}//如果i的后K个字符加上x形成回文串,就跳过(为了防止K为偶数当前j长度为奇数的错误)if (i >= K + 1 && IsPalindrome[K + 1][j << 1 | x]) {continue;}//如果向右移动一位并且最右边为x时合法,累加方案数dp[i][CurState] += dp[i - 1][j];dp[i][CurState] %= mod;}}}

值得注意的是这一段代码:

    if (i >= K + 1 && IsPalindrome[K + 1][j << 1 | x]) {continue;}

如果当前j的状态为0010,xxx=0,则j往右一位变成0100,不是回文串,当是此时00100已经形成了回文串。因为回文串长度的奇偶有些差异,因此需要在向右判断一位。
AC代码

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
constexpr static int inf = 0x3f3f3f3f;
constexpr static int mod = 1000000007;
int N, K;
int dp[401][(1 << 11) | 1];
bool IsPalindrome[12][(1 << 11) | 1]{ false };
//i=4 return 0110
int getBit(const int&i) {return (1 << i - 1) - 2;
}
void InitPalindrome() {IsPalindrome[1][0] = IsPalindrome[1][1] = true;IsPalindrome[2][0] = IsPalindrome[2][3] = true;for (int i = 3; i <= 11; ++i) {for (int j = 0; j <= (1 << i) - 1; ++j) {IsPalindrome[i][j] = IsPalindrome[i - 2][(j & getBit(i)) >> 1] && ((j >> i - 1) == (j & 1));}}
}
int getState(int State, int Last) {if (State >= 1 << K - 1) {State -= 1 << K - 1;}return State << 1 | Last;
}
int DP() {memset(dp, 0x0, sizeof(dp));dp[0][0] = 1;for (int i = 1; i <= N; ++i) {for (int j = 0; j <= (1 << K) - 1; ++j) {if (dp[i - 1][j] == 0) {continue;}for (int x = 0; x <= 1; ++x) {int&& CurState = getState(j, x);if (i >= K && IsPalindrome[K][CurState]) {continue;}if (i >= K + 1 && IsPalindrome[K + 1][j << 1 | x]) {continue;}dp[i][CurState] += dp[i - 1][j];dp[i][CurState] %= mod;}}}int&& Ans = 0;for (int i = 0; i <= (1 << K) - 1; ++i) {Ans = (Ans + dp[N][i]) % mod;}return Ans;
}
int main() {int T;ios::sync_with_stdio(false);cin >> T;InitPalindrome();for (int Case = 1; Case <= T; ++Case) {cin >> N >> K;cout << DP() << endl;}return 0;
}

禁止的回文子串 Dyslexic Gollum相关推荐

  1. java 最长回文_【Java】【每日算法/刷穿 LeetCode】5. 最长回文子串(中等)

    首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]5. 最长回文子串(中等) 宫水三叶发布于 今天 12:00 题目描述 给你一个字符串 s,找到 s 中最长的回文子串. 示例 ...

  2. leetcode--最长回文子串--python

    文章目录 题目 题目详情 示例 解题思路 思路 代码 运行结果 最佳方案 题目 题目详情 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 输入: &qu ...

  3. 刻意练习:LeetCode实战 -- Task17. 最长回文子串

    背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务.本期训练营采用分类别练习的模式,即选择了五个知识点(数组.链表.字符串.树.贪心算法),每个知 ...

  4. LeetCode实战:最长回文子串

    题目英文 Given a string s, find the longest palindromic substring in s. You may assume that the maximum ...

  5. leetcode 5 :Longest Palindromic Substring 找出最长回文子串

    题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...

  6. HDU 1544 Palindromes(回文子串)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1544 问题分析: 问题要求求出字符串的连续子串中的回文子串个数.首先,需要区分连续子串与子序列的区别. ...

  7. LeetCode 5 最长回文子串

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &quo ...

  8. python【力扣LeetCode算法题库】5- 最长回文子串

    5. 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab&quo ...

  9. 题目1252:回文子串

    题目描述: 输入一个字符串,输出该字符串中对称的子字符串的最大长度. 比如输入字符串"google",由于该字符串里最长的对称子字符串是"goog",因此输出4 ...

最新文章

  1. Confluence 6 有关空间的一些提示
  2. 面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答。...
  3. python 难度-Python分析 oj 网的题目难度和通过率的关系
  4. php学历低,学历低学起php来难不难
  5. Java读写文件的几种方式
  6. ES6类的使用和定义.Json.Promise对象的使用
  7. Mysql1 晨考题
  8. 说说windows下64位程序和32位程序
  9. Visio使用技巧总结
  10. 数学基础 - 第十一章 三角形
  11. html5 indexedDB 数据库 详讲
  12. jmeter监控服务器插件jp@gc - PerfMon Metrics Collector报错 Operation timed out
  13. linux增加swap空间的方法
  14. vscode 怎么设置背景图片
  15. 房东:你敢申报,我就涨房租!今冬,我一个程序员朋友离开了北京……
  16. 【工具】动图展示 60+ 个前端常用插件库合集
  17. sap 流程图 退货销售订单_销售订单_退货入库及退款(采用高级退货)
  18. VMware亮相全球云计算大会
  19. 揭秘美国云计算 大企业是第一推动力
  20. 泰戈尔《世界上最远的距离》

热门文章

  1. 网络安全领域中CISP证书八大类都有什么
  2. 已解决:Incorrect string value: '\xF0\x9F\x98\x83' for column 'nick_name' at row 1;
  3. IEEE-754 64位双精度浮点数存储详解
  4. 免费下载430套大型商业源码
  5. 福利篇2——嵌入式岗位笔试面试资料汇总(含大厂笔试面试真题)
  6. magento模板文件结构
  7. 维特比算法 python_维特比算法实现分词
  8. 维特比算法的python的简单实现
  9. MySql实验嵌套查询_实验五 数据库的嵌套查询实验
  10. 小程序商城|微信小程序商城系统