禁止的回文子串 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 ...
随机推荐
- celery学习
1.清空队列:celery -A 项目名称 purge 2.原理参考 https://www.cnblogs.com/sui776265233/p/10004679.html 消息中间件(messa ...
- 攻防世界-unseping(序列化,Bash shell)
这是一道序列化的题目,结合了Linux Bash shell知识 一.基础知识点 序列化 序列化的概念: 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式 ...
- CSS中的选择( ::selection和user-select)
CSS中的选择( ::selection和user-select) 在网络上,我们出于不同原因选择内容,也许我们想复制文本并在某处引用它.对于移动端来说,选择内容比较难,我不喜欢在移动端选择内容. ...
- python测试IP地址是否ping通
import timeimport osdef pingComputer(): for i in range(1, 256): host = '192.168.2.' + str(i) status1 ...
- mybatisplus SQL一对多
https://blog.csdn.net/Isyoubao/article/details/122212113 重点:<collection property="nspSchedul ...
- 在VSCODE的终端运行Python时汉字乱码问题处理
问题描述 在VSCODE的终端运行Python时,打印输出中文时汉字出现乱码, 文件编码都是UTF-8 解决步骤 1.打开Settings配置窗口(Ctrl+,) 2.搜索:code-runner.e ...
- Redis 突然变慢了如何排查并解决?
业务场景 某购物平台打算举行"双十一"大型购物狂欢活动,到了半夜12点用户数量暴增,出现了一个技术故障,用户发现自己无法下单!!! 技术组立即组织人手进行故障排查,结论是 Redi ...
- Java lombok包中的常用注解,便捷化开发POJO类
lombok包中的一些常用注解 如何使用Lombok?Lombok提供注解方式来提高代码的简洁性,常用注解有: @Data @Setter @Getter @NonNull @ ...
- 在Vue项目中使用wangEditor
wangEditor官网 封装的Editor组件 <template> <div class="editor-wrap"> <div ref=&quo ...
- zabbix(历史数据保留时长和趋势存储时间的区别)
zabbix(历史数据保留时长和趋势存储时间的区别)? zabbix(历史数据保留时长和趋势存储时间分别影响着哪里)? 001.影响grafana 数据展示的是历史数据还是趋势数据? 等把<历史 ...