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还是1
for (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. LeetCode[5] 最长的回文子串

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

  2. 最长回文子串-LeetCode 5 Longest Palindromic Substring

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

  3. 最长回文子串(Longest Palindromic Substring)

    这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...

  4. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  5. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  6. 51nod1089(最长回文子串之manacher算法)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...

  7. 求最长回文子串:Manacher算法

    主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...

  8. [译+改]最长回文子串(Longest Palindromic Substring) Part II

    [译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...

  9. [译]最长回文子串(Longest Palindromic Substring) Part I

    [译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...

  10. Manacher's algorithm: 最长回文子串算法

    Manacher 算法是时间.空间复杂度都为 O(n) 的解决 Longest palindromic substring(最长回文子串)的算法.回文串是中心对称的串,比如 'abcba'.'abcc ...

随机推荐

  1. navicat图形工具和pymysql模块的使用

    一 Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库 官网下载:http ...

  2. 123data路径

    /zhf/Innosky2021/data/dayantahttp://123.xx.xx.147:8888/cesiumdemo/data/dayanta/tileset.json

  3. Jenkins自动化部署(linux环境)---执行脚本

    1.安装node插件 2.node全局配置 3.填写jenkins构建时执行的shell脚本 完整命令 node -v npm install rm -rf ./dist/* npm run buil ...

  4. fetchAllAssoc 小分析

    这个函数出现在了两个地方 includes\database\database.inc line 2245 includes\database\prefetch.inc line 481 foreac ...

  5. color-color diagram data

  6. 【Selenium IDE】下载安装Chrome和Firefox插件IDE ide了解就行 不是重点 重点是写脚本

    下载安装Chrome和Firefox插件IDE 1.Chrome的IDE安装(1)由于chrome的限制所以提供了一个小方法:链接: https://www.crx4chrome.com/crx/77 ...

  7. Vulnhub 靶场 CORROSION: 2

    Vulnhub 靶场 CORROSION: 2 前期准备 下载地址:https://www.vulnhub.com/entry/corrosion-2,745/ 靶机地址:192.168.147.19 ...

  8. 可汗儿童版kids安卓版下载安装教程

    可汗儿童版kids安卓版幼儿版下载安装教程 点击下面 http://vip.ho27.com/Khan.apk 备用下载链接 天翼网盘下载安装就行 https://cloud.189.cn/t/6RV ...

  9. CxImageJPG

    typedef struct tag_ExifInfo { char Version [5]; //EXIF 信息版本 char CameraMake [32]; //DC 制造商 char Came ...

  10. rn项目下载@ant-design/react-native时发生冲突

    rn项目,使用npm i @ant-design/react-native下载antd. 下载依赖时报错: 如果你也遇到这个问题,直接告诉你结论,那就是最新的@ant-design/react-nat ...