Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)
1.5 seconds
512 megabytes
standard input
standard output
Tomorrow Ann takes the hardest exam of programming where she should get an excellent mark.
On the last theoretical class the teacher introduced the notion of a half-palindrome.
String t is a half-palindrome, if for all the odd positions i ()
the following condition is held: ti = t|t| - i + 1,
where |t| is the length of string tif
positions are indexed from 1. For example, strings "abaa",
"a", "bb", "abbbaa"
are half-palindromes and strings "ab", "bba"
and "aaabaa" are not.
Ann knows that on the exam she will get string s, consisting only of letters a and b,
and number k. To get an excellent mark she has to find the k-th
in the lexicographical order string among all substrings of s that are half-palyndromes. Note that each substring in this order is
considered as many times as many times it occurs in s.
The teachers guarantees that the given number k doesn't exceed the number of substrings of the given string that are half-palindromes.
Can you cope with this problem?
The first line of the input contains string s (1 ≤ |s| ≤ 5000),
consisting only of characters 'a' and 'b',
where |s| is the length of string s.
The second line contains a positive integer k — the lexicographical number of the requested string among all the half-palindrome substrings
of the given string s. The strings are numbered starting from one.
It is guaranteed that number k doesn't exceed the number of substrings of the given string that are half-palindromes.
Print a substring of the given string that is the k-th in the lexicographical order of all substrings of the given string that are
half-palindromes.
abbabaab
7
abaa
aaaaa
10
aaa
bbaabb
13
bbaabb
By definition, string a = a1a2... an is
lexicographically less than string b = b1b2... bm,
if either a is a prefix of b and
doesn't coincide withb, or there exists such i,
that a1 = b1, a2 = b2, ... ai - 1 = bi - 1, ai < bi.
In the first sample half-palindrome substrings are the following strings — a, a, a, a, aa, aba, abaa, abba, abbabaa, b, b, b, b, baab,bab, bb, bbab, bbabaab (the
list is given in the lexicographical order).
http://codeforces.com/contest/557/problem/E
大致题意:找出s的子串中字典序第k小的“半回文串”,给出半回文串定义是:对于随意i<=|s|/2 有s[i] = s[len-i+1]
数据量是5000
O(n^2)的算法可行
简单暴力的方法就是n^2 dp 出(i,j)的子串是不是半回文串,再把全部子串插入字典树。在dfs遍历出第k小的串
方法二,dp[i][j]统计出以i为始端到i~j的子串是回文串的总数。再把全部子串插入字典树,然后二分出答案子串。
方法一:
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll; const int N = 5000+5;
int dp[N][N];
char s[N];
int k;
int n;
struct node
{
node *son[2];
int cnt;
node()
{
memset(son,0,sizeof(son));
cnt = 0;
}
}trie[N*N];
int SZ = 0;
node *root,*cur;
node *createnode()
{
return &trie[SZ++];
}
void Insert(int p)
{
cur = root;
for(int i = p;i <= n;i++)
{
int val = s[i]-'a';
if(cur->son[val] == NULL) cur->son[val] = createnode();
cur = cur->son[val];
cur->cnt += dp[p][i];
}
}
int getsum(node *cur)
{
int sum = 0;
if(cur->son[0]) sum += getsum(cur->son[0]);
if(cur->son[1]) sum += getsum(cur->son[1]);
cur->cnt += sum;
return cur->cnt;
}
vector<char>ans;
bool dfs(node *cur,int &k)
{
if( k <= 0) return true;
if(cur->son[0])
{
ans.push_back('a');
if(cur->son[0]->cnt) k -= cur->son[0]->cnt;
if(dfs(cur->son[0],k)) return true;
ans.pop_back();
}
if(cur->son[1])
{
ans.push_back('b');
if(cur->son[1]->cnt)k -= cur->son[1]->cnt;
if(dfs(cur->son[1],k)) return true;
ans.pop_back();
}
return false;
}
int main()
{
scanf("%s%d",s+1,&k);
n = strlen(s+1);
for(int i =0;i <= n+2;i++)
for(int j = i;j >= 0;j--)
dp[i][j] = 1;
for(int len = 2;len <= n;len++)
for(int l = 1;l+len-1 <= n;l++)
{
int r = l+len-1;
dp[l][r] = (s[l] == s[r] && dp[l+2][r-2]);
}
root = createnode();
REP(i,n)Insert(i);
dfs(root,k);
foreach(i,ans) putchar(*i);
}
方法二:
//GNU C++ Accepted 374 ms 392200 KB
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll; const int N = 5000+5;
int dp[N][N];
char s[N];
int k;
int n;
struct node
{
node *son[2];
int cnt;
node()
{
memset(son,0,sizeof(son));
cnt = 0;
}
}trie[N*N];
int SZ = 0;
node *root,*cur;
node *createnode()
{
return &trie[SZ++];
}
void Insert(int p)
{
cur = root;
for(int i = p;i <= n;i++)
{
int val = s[i]-'a';
if(cur->son[val] == NULL) cur->son[val] = createnode();
cur = cur->son[val];
if(i != p)cur->cnt += dp[p][n]-dp[p][i-1];
else cur->cnt += dp[p][n];
}
} void query(node*cur,int k) //二分过程
{
if(k <= 0) return ;
if(cur->son[0] && cur->son[0]->cnt >= k)
{
int cnt = cur->son[0]->cnt;
cur = cur->son[0];
if(cur->son[0]) cnt -= cur->son[0]->cnt;
if(cur->son[1]) cnt -= cur->son[1]->cnt;
putchar('a');
query(cur,k-cnt);
}
else if(cur->son[1])
{
if(cur->son[0]) k -= cur->son[0]->cnt;
int cnt = cur->son[1]->cnt;
cur = cur->son[1];
if(cur->son[0]) cnt -= cur->son[0]->cnt;
if(cur->son[1]) cnt -= cur->son[1]->cnt;
putchar('b');
query(cur,k-cnt);
}
} int main()
{
scanf("%s%d",s+1,&k);
n = strlen(s+1);
for(int i =0;i <= n+2;i++)
for(int j = i;j >= 0;j--)
dp[i][j] = 1;
for(int len = 2;len <= n;len++)
for(int l = 1;l+len-1 <= n;l++)
{
int r = l+len-1;
dp[l][r] = (s[l] == s[r] && dp[l+2][r-2]);
} REP(i,n)
for(int j = i+1;j <= n;j++) dp[i][j] += dp[i][j-1];
root = createnode();
REP(i,n) Insert(i);
query(root,k);
}
Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)的更多相关文章
- Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome 字典树/半回文串
E. Ann and Half-Palindrome Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...
- Codeforces Round #343 (Div. 2) D - Babaei and Birthday Cake 线段树+DP
题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和. 思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况 ...
- Codeforces Round #338 (Div. 2) B. Longtail Hedgehog 记忆化搜索/树DP
B. Longtail Hedgehog This Christmas Santa gave Masha a magic picture and a pencil. The picture con ...
- Codeforces Round #311 (Div. 2) A,B,C,D,E
A. Ilya and Diplomas 思路:水题了, 随随便便枚举一下,分情况讨论一下就OK了. code: #include <stdio.h> #include <stdli ...
- Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 图论
D. Vitaly and Cycle Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...
- Codeforces Round #311 (Div. 2) C. Arthur and Table Multiset
C. Arthur and Table Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...
- Codeforces Round #311 (Div. 2)B. Pasha and Tea 水题
B. Pasha and Tea Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/prob ...
- Codeforces Round #311 (Div. 2) A. Ilya and Diplomas 水题
A. Ilya and Diplomas Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/ ...
- Codeforces Round #311 (Div. 2)题解
A. Ilya and Diplomas time limit per test 1 second memory limit per test 256 megabytes input standard ...
随机推荐
- CCSpawn使用CCRepeatForever无效
在使用CCSpawn中加入CCRepeatForever,但却无法使用CCRepeatForever的效果. CCActionInterval* action =(CCActionInterval*) ...
- Multi-touch.
TP(Multi-touch). 1.Win7有6个版本,分别如下. Windows 7 Starter (初级版) 不支 ...
- Hibernate简单的基础理论
和Hibernate有关的概念,是掌握Hibernate必须了解的知识.就个人经验来说,可以在了解如何简单开发Hibernate之后,再来学习这些概念,这样可以有个比较清楚的认识.Hibernate是 ...
- Android WifiDirect 学习(三) 一些基础知识和问题
P2P架构介绍 P2P架构中定义了三个组件,一个设备,两种角色.这三个组件分别是: P2P Device:它是P2P架构中角色的实体,读者可把它当做一个Wi-Fi设备. P2P Group Owner ...
- T-SQL 一次插入多行数据
使用 INSERT SELECT 向表中插入数据 --将t1中查询到的数据插入添加到t2中(t2表必须存在,且顺序.数据类型必须与t1一致) INSERT INTO t2(USERNAME,PASSW ...
- SSAS数据集Cube不存在或者尚未处理
对Microsoft SQL Server(2008) Analysis Services(以下称SSAS) 多维数据集运行多维表达式 (MDX) 查询时,会返回这个错误消息:XXX Cube不存在, ...
- Oracle怎样方便地查看报警日志错误
由于报警日志文件很大,而每天都应该查看报警日志(查看有无“ORA-”,Error”,“Failed”等出错信息),故想找到一种比较便捷的方法,查看当天报警日志都有哪些错误. 在网上查了几天的资料,尝试 ...
- Linux 定时执行shell脚本_crontab
1.查看任务[oracle@XXXXX OracleBackA]$ crontab -l 2.新增任务[oracle@XXXXX OracleBackA]$ crontab -e 3.每天14点40执 ...
- C++基于模板顺序表的实现(带排序)
说明:代码是可以运行的,但是发表在博客上后复制到编译器里面报N多错误,找了半天原因是网页里面生成了一些空白字符,这些字符编译器无法识别. 因此使用了2种插入格式插入代码. 第二个带注释解释的代码不可复 ...
- SSH-key密钥生成
为了能够不用输入密码访问git库(github/gitlab),需要使用ssh key ssh-keygen -t rsa -C "<your email address>&qu ...