禁止的回文子串 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 ...
随机推荐
- elasticsearch组件
elasticsearch组件 Elasticsearch 是一个实时的分布式搜索分析引擎,它能让你以前所未有的速度和规模,去探索你的数据. 它被用作全文检索.结构化搜索.分析以及这三个功能的组合 E ...
- 一、MySQL 函数
1.MySQL 字符串函数 函数 描述 实例 结果展示 说明 REPLACE(s,s1,s2) 将字符串s2代替字符串s中的字符串s1 SELECT REPLACE(ccc.contract_no,& ...
- windows sshd powershell 配置
安装sshd打开"设置",选择"应用">"应用和功能",然后选择"可选功能" .扫描列表,查看是否已安装 Open ...
- Linux 常用监控指标总结
1. Linux运维基础采集项 做运维,不怕出问题,怕的是出了问题,抓不到现场,两眼摸黑.所以,依靠强大的监控系统,收集尽可能多的指标,意义重大.但哪些指标才是有意义的呢,本着从实践中来的思想,各位工 ...
- Android Custom View使用Databinding
Android Custom View是可以使用 databinding 的 //java.lang.IllegalArgumentException: View is not a binding l ...
- What is REST and Restful?
什么是rest 和 restful? 提出rest的作者,目的:符合框架原理的情况下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强,性能好,适宜通讯的架构. Fielding将他对互联网 ...
- HTML语言基本标签
创建一个HTML文档 <html></html> 设置文档标题以及其他不在WEB网页上显示的信息 <head></head> 设置文档的可见部分 < ...
- C语言学习--指针函数与函数指针
#include<stdio.h> #include<string.h> //指针函数: 是一个函数, 但是这个函数的返回值类型是一个指针 //函数指针: 是一个指针, 这个指 ...
- Java课堂学习总结
对于Java字段的初始化来说,共有以下几种方法: 1.类的构造函数(构造方法):当创建一个对象时,其构造函数就会自动调用.构造方法必须与类名相同,无返回值.如果程序员没有定义一个构造函数时,系统会自动 ...
- 牛客 二叉树中和为某一值的路径 【时间19ms】【内存9560k】
https://www.nowcoder.com/practice/b736e784e3e34731af99065031301bca 构造函数:new ArrayList(al)把al的所有值复制到 ...