【POJ2887】Big String(块状链表,模板)

举报
小哈里 发表于 2022/05/10 23:13:56 2022/05/10
【摘要】 problem 给一个字符串,长度不超过 1e6,有两种操作: 在第 i 个字符的前面添加一个字符 ch查询第 k 个位置是什么字符 操作的总数不超过 2000 solution 1、传统的数组...

problem

给一个字符串,长度不超过 1e6,有两种操作:

  1. 在第 i 个字符的前面添加一个字符 ch
  2. 查询第 k 个位置是什么字符

操作的总数不超过 2000

solution

1、传统的数组所有数据在内存中是紧凑储存的,优点是定位快:O(1),缺点是修改慢:O(n)
2、传统的链表每个节点只记录一个字符,优缺点与数组正好相反:定位慢 O(n),修改快 O(1)
3、块状链表的每个节点记录的是 sqrt(n) 个信息,一个长度为 n 的字符串就被分成了 sqrt(n) 个。这样,查询和插入字符的操作就变成了 sqrt(n)级别的了,对于这题 2000 个操作来讲,时间复杂度还能忍受
4、在实际应用中,需维持块状链表的每个结点大小在[sqrt(n)/2,2∗sqrt(n)],否则时间会退化的很厉害。(超过了就将一个结点分裂成两个)

codes

#include<cstdio>
#include<cstring>
const int maxn = 2000, maxlen = 1e6+10;//sqrt(1e6)

struct Block_List{
    struct Node{
        char buff[maxn];
        int size, next;
        void init(){
            size = 0, next = -1;
            memset(buff,0,sizeof(buff));
        }
    }List[maxn];
    int head, tot;

    void init(char s[]){
        head = tot = 0;
        List[tot++].init();
        int cur = 0;
        for(int i = head; s[cur]; i = List[i].next){
            for(int j = 0; j < maxn && s[cur]; j++,cur++){
                List[i].buff[j] = s[cur];
                List[i].size++;
            }
            if(s[cur]){
                List[tot].init();
                List[i].next = tot++;
            }
        }
        for(int i = head; i!=-1; i = List[i].next)
            if(List[i].size==maxn)Split(i);
    }

    void Split(int id){
        List[tot].init();
        for(int i = maxn/2; i < maxn; i++){
            List[tot].buff[i-maxn/2] = List[id].buff[i];
            List[tot].size++;
            List[id].buff[i] = 0;
            List[id].size--;
        }
        List[tot].next = List[id].next;
        List[id].next = tot++;
    }

    void Insert(int pos, char val){
        int i;
        for(i = head; pos > List[i].size && List[i].next != -1; i = List[i].next)
            pos -= List[i].size;
        if(pos >= List[i].size)List[i].buff[List[i].size] = val;
        else {
            for(int j = List[i].size; j > pos; j--)
                List[i].buff[j] = List[i].buff[j-1];
            List[i].buff[pos] = val;
        }
        List[i].size++;
        if(List[i].size==maxn)Split(i);
    }

    char Find(int pos){
        int i;
        for(i = head; pos > List[i].size; i = List[i].next)
            pos -= List[i].size;
        return List[i].buff[pos-1];
    }
}Meow;

char op[2], buff[maxlen];
int pos;

int main(){
    scanf("%s",buff);
    Meow.init(buff);
    int n;  scanf("%d",&n);
    for(int i = 0; i < n; i++){
        scanf("%s",op);
        if(op[0]=='I'){
            scanf("%s%d",buff,&pos);
            Meow.Insert(pos-1,buff[0]);
        }else {
            scanf("%d",&pos);
            printf("%c\n",Meow.Find(pos));
        }
    }
    return 0;
}

文章来源: gwj1314.blog.csdn.net,作者:小哈里,版权归原作者所有,如需转载,请联系作者。

原文链接:gwj1314.blog.csdn.net/article/details/81534777

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。