BZOJ 1507 Editor(塊狀鏈表)

題目連接:http://61.187.179.132/JudgeOnline/problem.php?id=1507php

題意:一個文本編輯器,模擬如下操做:node

思路:塊狀鏈表的主要操做:編輯器

(1)find(p,b):找到位置p在鏈表的位置b;spa

(2)split(b,p):將第b塊分裂成兩塊,前一塊大小爲p;get

(3)maintain(b):將b塊以後的碎片合併;it

利用以上三種操做能夠完成插入串、刪除一段串、獲得一段串三種操做。另外三種操做比較簡單。文本編輯器

(1)insert(p,n,str):在位置p以後插入長度爲n的串str。find(p,b),split(b,p),以後將str插入b以後,最後maintain(b)一下;queue

(2)erase(p,n):在位置p以後刪除長度爲n的一段。find(p,b),split(b,p),以後從b以後刪除若干塊。這裏可能最後一塊也是須要split的。im

(3)get(p,n):獲得p以後長度爲n的一段。find(p,b),split(b,p),以後從b以後取出長度爲n的串,這裏可能最後一個串也是須要split的。鏈表




const int N=1<<25;
const int BLOCKSIZE=20000;
const int BLOCKNUM=N/BLOCKSIZE*3;


queue<int> Q;


int newNode()
{
    int temp=Q.front();
    Q.pop();
    return temp;
}


void delNode(int t)
{
    Q.push(t);
}


struct node
{
    char data[BLOCKSIZE];
    int len,next;
};


node a[BLOCKNUM];


void find(int &p,int &b)
{
    for(b=0;a[b].next!=-1&&p>a[b].len;b=a[b].next)
    {
        p-=a[b].len;
    }
}


void fillNode(int b,int n,char data[],int nextB)
{
    a[b].next=nextB;
    a[b].len=n;
    memcpy(a[b].data,data,n);
}


void split(int b,int p)
{
    if(a[b].len==p) return;
    int t=newNode();
    fillNode(t,a[b].len-p,a[b].data+p,a[b].next);
    a[b].next=t;
    a[b].len=p;
}


void maintain(int b)
{
    int t;
    for(;b!=-1;b=a[b].next)
    {
        for(t=a[b].next;t!=-1&&a[b].len+a[t].len<=BLOCKSIZE;t=a[b].next)
        {
            memcpy(a[b].data+a[b].len,a[t].data,a[t].len);
            a[b].len+=a[t].len;
            a[b].next=a[t].next;
            delNode(t);
        }
    }
}


void insert(int p,int n,char str[])
{
    int i,b,t;
    find(p,b); split(b,p);
    for(i=0;i+BLOCKSIZE<=n;i+=BLOCKSIZE)
    {
        t=newNode();
        fillNode(t,BLOCKSIZE,str+i,a[b].next);
        a[b].next=t;
        b=t;
    }
    if(i<n)
    {
        t=newNode();
        fillNode(t,n-i,str+i,a[b].next);
        a[b].next=t;
    }
    maintain(b);
}


void erase(int p,int n)
{
    int i,b,t;
    find(p,b); split(b,p);
    for(i=a[b].next;i!=-1&&n>a[i].len;i=a[i].next)
    {
        n-=a[i].len;
    }
    split(i,n); i=a[i].next;
    for(t=a[b].next;t!=i;t=a[b].next)
    {
        a[b].next=a[t].next;
        delNode(t);
    }
    maintain(b);
}


void get(int p,int n,char str[])
{
    int i,b,t;
    find(p,b);i=min(n,a[b].len-p);
    memcpy(str,a[b].data+p,i);
    for(t=a[b].next;t!=-1&&i+a[t].len<=n;t=a[t].next)
    {
        memcpy(str+i,a[t].data,a[t].len);
        i+=a[t].len;
    }
    if(i<n&&t!=-1) memcpy(str+i,a[t].data,n-i);
    str[n]=0;
}


void init()
{
    int i;
    FOR1(i,BLOCKNUM-1) Q.push(i);
    a[0].next=-1;
    a[0].len=0;
}


char str[N];


void read(int n)
{
    int i;
    char c;
    FOR0(i,n)
    {
        c=getchar();
        str[i]=c;
        if(c<32||c>126) i--;
    }
}


int main()
{
    init();
    int cur=0;
    char op[10];
    int n;
    rush()
    {
        RD(op);
        if(op[0]=='M') RD(cur);
        else if(op[0]=='I')
        {
            RD(n);
            read(n);
            insert(cur,n,str);
        }
        else if(op[0]=='D')
        {
            RD(n);
            erase(cur,n);
        }
        else if(op[0]=='G')
        {
            RD(n);
            get(cur,n,str);
            puts(str);
        }
        else if(op[0]=='P') cur--;
        else if(op[0]=='N') cur++;
    }
}

相關文章
相關標籤/搜索