CodeForces - 557E(trie

题目:给出一个只有ab组成的串,求其中半回文串的第k大。

思路:暴力枚举出所有半回文串,然后暴力插到trie里查询第k大,原先写trie是抄模板的,这次自己写了一下。

#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
#define pb push_back
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps 0.0000000001
#define IINF (1<<30)
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int charsize=2;
const int maxv=5005;
const int maxpool=25000000;
bool ispa[maxv][maxv];
char str[maxv];
int len,k;
struct Node{
    int num;
    int sum;
    Node *ch[charsize];
    Node():num(0),sum(0){};
}pool[maxpool];
Node *null=new Node();
int poolh=0;
Node *newNode(){
    Node *n=&pool[poolh++];
    for(int i=0;i<charsize;i++) n->ch[i]=null;
    n->sum=n->num=0;
    return n;
}
Node *root=newNode();
void insert(Node* n,int p,int s){
    while(p<len){
        if(n->ch[str[p]-‘a‘]==null) n->ch[str[p]-‘a‘]=newNode();
        if(ispa[s][p]) n->ch[str[p]-‘a‘]->num++;
        n=n->ch[str[p]-‘a‘],p++;
    }
}
void cul(Node *n){
    if(n==null) return;
    n->sum=n->num;
    for(int i=0;i<charsize;i++){
        cul(n->ch[i]);
        n->sum+=n->ch[i]->sum;
    }
}
void output(Node *n,int k){
    if(n==null||k<=0) return;
    int sum=0;
    for(int i=0;i<charsize;i++){
        if(sum+n->ch[i]->sum>=k){
            printf("%c",(char)(‘a‘+i));
            output(n->ch[i],k-sum-n->ch[i]->num);
            return;
        }
        sum+=n->ch[i]->sum;
    }
    return;
}
void getpa(){
    for(int i=0;i<len;i++){
        for(int j=0;j<=len;j+=2){
            if(i-j<0||i+j>=len){
                break;
            }
            if(str[i+j]==str[i-j]){
                ispa[i-j][i+j]=1;
            }else{
                break;
            }
        }
        for(int j=1;j<=len;j+=2){
            if(i-j<0||i+j>=len){
                break;
            }
            if(str[i+j]==str[i-j]){
                ispa[i-j][i+j]=1;
            }else{
                break;
            }
        }
        for(int j=0;j<=len;j+=2){
            if(i-j<0||i+j+1>=len){break;}
            if(str[i-j]==str[i+j+1]){
                ispa[i-j][i+j+1]=1;
            }else{
                break;
            }
        }
        for(int j=1;j<=len;j+=2){
            if(i-j<0||i+j+1>=len){break;}
            if(str[i-j]==str[i+j+1]){
                ispa[i-j][i+j+1]=1;
            }else{
                break;
            }
        }

    }
}
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    /*    std::ios::sync_with_stdio(false);
        std::cin.tie(0);*/
    scanf("%s",str);
    len=strlen(str);
    cin>>k;
    getpa();
    for(int i=0;i<len;i++) insert(root,i,i);
    cul(root);
    output(root,k);
    return 0;
}

时间: 2024-08-06 13:26:06

CodeForces - 557E(trie的相关文章

[字典树] Codeforces 557E Ann and Half-Palindrome

题意: 给一个长度为5000的ab串,问你第k大的半回文子串是什么 所谓的半回文串就是下标是奇数的位置前后相等就好了. 思路: 首先发现串的长度只有5000,可以做一个类似区间dp的预处理 处理出dp[i][j]代表第i到j子串是不是半回文子串 然后依次把原串的所有子串插入字典树,并在节点标记个数 然后最后dfs一下k个就好了 代码: #include"cstdlib" #include"cstdio" #include"cstring" #in

数据结构专题

CodeForces 628E CodeForces 617E CodeForces 618E CodeForces 620E CodeForces 611E CodeForces 610D CodeForces 609F CodeForces 609E CodeForces 605D CodeForces 601D CodeForces 597C CodeForces 593D CodeForces 589G CodeForces 566D CodeForces 558D CodeForces

codeforces 455B A Lot of Games (Trie + dfs)

题目大意: 两个人往一个空的字符串里填单词,每一次只能填一个,而且填完之后要是给出的N个字符串的前缀. 思路分析: 先用给出的所有单词建字典树. 然后从根节点开始dfs. win [x] 表示踩在x节点上是否有必胜策略 lose [x] 表示踩在x节点上是否有必败策略. 然后是博弈的过程. 如果先手有必胜和必败的策略,那么他可以一直输到k-1 如果只有必胜策略.那么只有当k为奇数的时候它才能赢. 其他为后手赢. #include <cstdio> #include <iostream&g

Educational Codeforces Round 23 E. Choosing The Commander (trie)

题目链接: Educational Codeforces Round 23 E. Choosing The Commander 题意: 一共有n个操作. 1.  插入一个数p 2.  删除一个数p 3.  询问有多少个数 使得 x^p<l 题解: 对于前两种操作用01trie就能解决. 对于对三个操作,我们考虑在trie上搜索. 1.  当l的bit位是1时,那边bit位是p的字数全部的数都会小于l,(因为p^p=0) 2.  当l的bit为是0时,那边只能向bit位是p的子树中搜. 这样算下来

trie树 Codeforces Round #367 D Vasiliy&#39;s Multiset

1 // trie树 Codeforces Round #367 D Vasiliy's Multiset 2 // 题意:给一个集合,初始有0,+表示添加元素,-去除元素,?询问集合里面与x异或最大的值 3 // 思路:思路很好想,建立trie树,再贪心当前位是1则选0,0则选1 4 5 6 #include <bits/stdc++.h> 7 using namespace std; 8 #define LL long long 9 const double inf = 123456789

Codeforces 888G Xor-MST - 分治 - 贪心 - Trie

题目传送门 这是一条通往vjudge的高速公路 这是一条通往Codeforces的高速公路 题目大意 给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\  xor\  a_{j})$.一个生成树的权值是各边的权值和.问最小生成树的权值. 设值域为$[0, 2^{k})$. 当$k = 1$的时候,显然将点权为0的点之间互相连边,点权为1的点之间互相连边,中间随便连一条. 当$k = x\ (x > 1)$的时候,将这些点按照二进制的第$k$位分成两

codeforces 282E. Sausage Maximization Trie

题目链接 给n个数, 让你找出一个前缀和一个后缀, 它们异或完以后最大, 前缀和后缀都是异或得来的, 可以为空, 为空时按0算.前缀后缀不可覆盖. 这题好神, 竟然是Trie树... 首先将所有数的异或算出来作为初始的后缀, 初始前缀为0. 然后往字典树里插入前缀, 在对后缀进行查找, 查找时, 从高位往低位找, 如果后缀的第i位为0, 那么就找字典树里这一位有没有1, 有1就往1的那一条路找,没有就只能往0那一条路找. 具体看代码. #include <iostream> #include

CodeForces #367 div2 D Trie

题目链接:Vasiliy's Multiset 题意:这里有一个set容器,有三种操作,+ num, - num, ? num,分别代表往容器里加上num,或者拿走num,或着从容器里找一个数temp使得temp^num的值最大.输出这个最大值. 思路:对于XOR操作,一般都要拆位考虑,拆完之后用Trie或者线段树维护,然后,这个题把每个数的二进制30位(前面不够的用0补全)插入Trie,查询的时候,对于每一位先尝试往相反的方向走,因为异或 只要越高位 相反值越大,然后再尝试往相同的方向走.最后

Educational Codeforces Round 12 E. Beautiful Subarrays trie求两异或值大于等于k对数

E. Beautiful Subarrays One day, ZS the Coder wrote down an array of integers a with elements a1,  a2,  ...,  an. A subarray of the array a is a sequence al,  al  +  1,  ...,  ar for some integers (l,  r) such that 1  ≤  l  ≤  r  ≤  n. ZS the Coder th