禁止的回文子串 Dyslexic Gollum

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的更多相关文章
- LeetCode[5] 最长的回文子串
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- 最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- 最长回文子串(Longest Palindromic Substring)
这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
- 1089 最长回文子串 V2(Manacher算法)
1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaaa ...
- 51nod1089(最长回文子串之manacher算法)
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...
- 求最长回文子串:Manacher算法
主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...
- [译+改]最长回文子串(Longest Palindromic Substring) Part II
[译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...
- [译]最长回文子串(Longest Palindromic Substring) Part I
[译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...
- Manacher's algorithm: 最长回文子串算法
Manacher 算法是时间.空间复杂度都为 O(n) 的解决 Longest palindromic substring(最长回文子串)的算法.回文串是中心对称的串,比如 'abcba'.'abcc ...
随机推荐
- [Oracle19C 数据库管理] 配置数据库审计
以下内容未经整理 占位 强制审计:无法关闭此审计,比如记录数据库的开启和关闭. 标准审计: 基于值得审计:创建触发器,基于值进行记录.Trigger占用资源多 细粒度审计:加一些where条件,针对触 ...
- MYSQL-数据操作DDL,DML,DCL,DQL
前言:MYSQL数据操作语言分为四种 1.DDL(数据定义语言):用来创建数据库中的表.索引.视图.存储过程.触发器等. 2.DML(数据操作语言):用来对表内数据的添加.更新.删除等. 3.DCL( ...
- 强烈推荐的elasticsearch集群连接工具: elasticvue
个人感觉非常棒的es-cluster连接工具, 检查状态什么的, 一目了然, 支持中文超方便, 比elasticSearchHead好用多了. 安装方法打开微软浏览器edge-商城搜索-Elastic ...
- centos6根分区扩容,非lvm
1.关闭虚拟机,删除里面的快照,将磁盘扩容 2.根分区为sda3,开机后输入fdisk /dev/sda,d,3删除sda3,然后n,p,3,w创建sda3,扇区的开始位置要一致 3.growpart ...
- SAP abap外部断点
如图所示:
- 记D365开发的最佳实践
前端JS 不同的需求应该划分模块,以便日后修改,也是为了职责分离,模块分离,日后如果想分离到单独的JS文件里面也是比较方便: 对于公共的查询函数,应该做缓存,优先使用sessionStorage. 多 ...
- 接口设置ip跨域
// 允许跨域请求的地址'allowUrls' => [ 'http://localhost:8080', 'http://192.168.2.224', 'http://192.168.2.2 ...
- 测试elasticsearch保存时报找不到类型的错误
java测试存储数据到es时报错:...ActionRequestValidationException: Validation Failed: 1: type is missing... /** * ...
- TypeScript 元组
TypeScript 元组 我们知道数组中元素的数据类型都一般是相同的(any[] 类型的数组可以不同),如果存储的元素数据类型不同,则需要使用元组. 元组中允许存储不同类型的元素,元组可以作为参数传 ...
- js正则 -180 到180 小数点后无限位、el-input
正则 -180 到180 小数点后无限位/^0$|^-?0\.\d*[1-9]$|^-?[1-9](\.\d*[1-9])?$|^-?[1-9]\d(\.\d*[1-9])?$|^-?1[0-7]\d ...