找出s的子串中字典序第k小的“半回文串” Trie Codeforce Div. 2 Ann and Half-Palindrome
2015-10-07 18:18
393 查看
http://codeforces.com/problemset/problem/557/E
题意
找出s的子串中字典序第k小的“半回文串”,给出半回文串定义是:对于任意i<=|s|/2 有s[i] = s[len-i+1]
思路
这用dp推下就可以了,dp[i][j]表从i到j是否是回文串
则dp[i][j] = dp[i+2][j-2](j-i>=4),其他的都是奇回文串;
要输出第k个字典序的子串,首先肯定想到要用字典树输出来就是了,很简单的dfs就可以了。插入串的时候,就不要一个一个插了,而直接插一个后缀就可以了这样总的复杂度也就是O(n * n),n是串的长度。
http://codeforces.com/blog/entry/18943
This problem can be solved with help of dynamic programming.
At first we calculate matrix good[][]. In good[i][j] we
put true, if substring from position i to
position j half-palindrome. Else we put ingood[i][j]false.
We can do it with iterating on "middle" of half-palindrome and expanding it to the left and to the right. There are 4 cases of "middle" but
we omit it because they are simple enough.
Now we need to use Trie and we will put in it suffixes of given string. Also we will store array cnt[]. In cnt[v] we
will store number of half-palindromes which ends in vertex v of our Trie. Let now we put in tree suffix which starts in position i,
current symbol of string which we put is in position j and we go in vertex v of
out Trie. Then if good[i][j] = true we add one to cnt[v].
Now with help of dfs let calculate for every vertex sum[v] — sum of numbers which stored in array cnt[] for
vertex v and for vertices in all subtrees of vertex v.
It is left only to restore answer. Start from root of our Trie. We will store answer in variable ans. In variable k store
number of required substring. Let now we in vertex v, by letter 'a' we
can go in vertex toa and
by letter 'b' — in vertex tob.
Then if sum[toa] ≤ k we
make ans + = 'a' and go in vertex toa of
our Trie. Else we need to make as follows: k — = sum[toa],ans + = 'b' and
go in vertex tob of
our Trie.
When k will be ≤ 0 print
resulting string ans and finish algorithm.
Asymptotic behavior of this solution — O(szalph * n2)
where szalph — size of input alphabet (in this problem it equals to two) and n —
length of given string.
http://codeforces.com/contest/557/submission/13470601
题意
找出s的子串中字典序第k小的“半回文串”,给出半回文串定义是:对于任意i<=|s|/2 有s[i] = s[len-i+1]
思路
这用dp推下就可以了,dp[i][j]表从i到j是否是回文串
则dp[i][j] = dp[i+2][j-2](j-i>=4),其他的都是奇回文串;
要输出第k个字典序的子串,首先肯定想到要用字典树输出来就是了,很简单的dfs就可以了。插入串的时候,就不要一个一个插了,而直接插一个后缀就可以了这样总的复杂度也就是O(n * n),n是串的长度。
http://codeforces.com/blog/entry/18943
This problem can be solved with help of dynamic programming.
At first we calculate matrix good[][]. In good[i][j] we
put true, if substring from position i to
position j half-palindrome. Else we put ingood[i][j]false.
We can do it with iterating on "middle" of half-palindrome and expanding it to the left and to the right. There are 4 cases of "middle" but
we omit it because they are simple enough.
Now we need to use Trie and we will put in it suffixes of given string. Also we will store array cnt[]. In cnt[v] we
will store number of half-palindromes which ends in vertex v of our Trie. Let now we put in tree suffix which starts in position i,
current symbol of string which we put is in position j and we go in vertex v of
out Trie. Then if good[i][j] = true we add one to cnt[v].
Now with help of dfs let calculate for every vertex sum[v] — sum of numbers which stored in array cnt[] for
vertex v and for vertices in all subtrees of vertex v.
It is left only to restore answer. Start from root of our Trie. We will store answer in variable ans. In variable k store
number of required substring. Let now we in vertex v, by letter 'a' we
can go in vertex toa and
by letter 'b' — in vertex tob.
Then if sum[toa] ≤ k we
make ans + = 'a' and go in vertex toa of
our Trie. Else we need to make as follows: k — = sum[toa],ans + = 'b' and
go in vertex tob of
our Trie.
When k will be ≤ 0 print
resulting string ans and finish algorithm.
Asymptotic behavior of this solution — O(szalph * n2)
where szalph — size of input alphabet (in this problem it equals to two) and n —
length of given string.
http://codeforces.com/contest/557/submission/13470601
#include<cstdio> #include<string> #include<cstring> #include<algorithm> #define For(i,x,y) for (int i=x;i<y;i++) #define Pb push_back using namespace std; const int N=5000+19,Top=20000000; int f ,n,k; char s ; string Ans; int DP(int L,int R) { if (~f[L][R]) return f[L][R]; return f[L][R]=L>=R?1:(s[L]==s[R]&&DP(L+2,R-2)); } //Trie int son[Top][2],cnt[Top],Sum[Top],tot,x,t,y; void DFS(int x) { Sum[x]=cnt[x]; For(i,0,2) if (int y=son[x][i]) DFS(y),Sum[x]+=Sum[y]; } void DFS_2(int x) { if (k<=cnt[x]) return;k-=cnt[x]; For(i,0,2) if (int y=son[x][i]) if (k>Sum[y]) k-=Sum[y];else {Ans.Pb(i+'a'),DFS_2(y);break;} } int main() { memset(f,-1,sizeof(f)); scanf("%s%d",s,&k);n=strlen(s); For(i,0,n) For(j,i,n) f[i][j]=DP(i,j); For(i,0,n) { x=0; For(j,i,n) { int &u=son[x][s[j]-'a']; if (!u) u=++tot;x=u; if (f[i][j]) cnt[x]++; } } DFS(0); DFS_2(0); puts(Ans.c_str()); }
相关文章推荐
- ZOJ 1115
- 位,字节,字的区别
- LeetCode(79) Word Search
- 0917 实验一词法分析程序
- ubuntu 安装LAMP web 服务器, phpmyadmin 安装后无法打开解决
- LeetCode(79) Word Search
- Hibernate 不同数据库的连接及SQL方言
- hdu4267A Simple Problem with Integers 线段树
- 1.3.5 head.s开始执行(3)
- Android内核sysfs中switch类使用实例
- java(Android)——内存泄露的一些经典案例
- C++实现KMP算法(优化版)
- 更换phpcms后台编辑器自动添加的<div>标签为<P>标签
- [多线程同步练习]PV操作
- 如何设置插入的Toolbar资源中按钮保持按下状态
- Android 数据存储--文件存储
- node lesson3
- win10 64位开机卡在登录界面的解决办法
- 【C语言】求1-1/2+1/3-1/4+1/5....+1/99-1/100
- 使用c#,WPF,模仿IPhone的Loading(加载)效果