參考資料
1)官方說明
支持
sorry,cena不支持rope
聲明
1)頭文件
#include<ext/rope>
2)調用命名空間
using namespace __gnu_cxx;
底層原理
查了資料,大概可以稱作可持久化平衡樹,因為rope適用於大量、冗長的串操作,而不適合單個字符操作官方說明如下:
Though ropes can be treated as Containers of characters, and are almost Sequences, this is rarely the most efficient way to accomplish a task. Replacing an individual character in a rope is slow: each character replacement essentially consists of two substring operations followed by two concatenation operations. Ropes primarily target a more functional programming style.Inserting a character in the middle of a 10 megabyte rope should take on the order of 10s of microseconds, even if a copy of the original is kept, e.g. as part of an edit history.It is possible to view a function producing characters as a rope. Thus a piece of a rope may be a 100MByte file, which is read only when that section of the string is examined. Concatenating a string to the end of such a file does not involve reading the file. (Currently the implementation of this facility is incomplete.)
另,根據網上資料,rope本質是封裝好的類似塊狀鏈表的東東,有人說是logn的,但也有說是n^0.5的。rope不支持一切數值操作,如第k大
小知識
先介紹幾個可能使用到的函數
1)append()
string &append(const string &s,int pos,int n);//把字符串s中從pos開始的n個字符連接到當前字符串的結尾
或
a.append(b);
2)substr()
s.substr(0,5);//獲得字符串s中從第零位開始長度為5的字符串(默認時長度為剛好開始位置到結尾)
定義/聲明
rope<char> str;
also
<crope>r="abcdefg"
具體內容
總的來說,
1)運算符:rope支持operator += -= + - < ==
2)輸入輸出:可以用<<運算符由輸入輸出流讀入或輸出。
3)長度/大小:調用length(),size()都可以哦
4)插入/添加等:
push_back(x);//在末尾添加x
insert(pos,x);//在pos插入x,自然支持整個char數組的一次插入
erase(pos,x);//從pos開始刪除x個
copy(pos,len,x);//從pos開始到pos+len為止用x代替
replace(pos,x);//從pos開始換成x
substr(pos,x);//提取pos開始x個
at(x)/[x];//訪問第x個元素
訪問
1)迭代器:不說,在競賽是超時大忌
2)單點訪問,直接用數組形式調用下標即可
應用
一、bzoj1269 文本編輯器
如果想看正常版本的看我的splay平衡樹代碼
實現操作:
1.(已知)move k:移動光標到目標,初始為0
2.(已知)prev:光標前移一個字符
3.(已知)next:光標后移一個字符
4.insert n s:在光標后插入長度為n的字符串s光標位置不變
5.delete n 刪除光標后的n個字符,光標位置不變
6.rotate n 反轉光標后的n個字符,光標位置不變
7.get 輸出光標后一個字符,光標位置不變
solution
為實現反轉操作且保證不超時,我們不調用rope自帶的可怕函數,暴力構建兩個rope,插入時一個正序插入一個倒序插入,區間即為子串賦值
#include<cstdio> #include<ext/rope> #include<iostream> using namespace std; using namespace __gnu_cxx; inline int Rin(){ int x=0,c=getchar(),f=1; for(;c<48||c>57;c=getchar()) if(!(c^45))f=-1; for(;c>47&&c<58;c=getchar()) x=(x<<1)+(x<<3)+c-48; return x*f; } int n,pos,x,l; rope<char>a,b,tmp; char sign[10],ch[1<<22],rch[1<<22]; int main(){ n=Rin(); while(n--){ scanf("%s",sign); switch(sign[0]){ case'M':pos=Rin();break; case'P':pos--;break; case'N':pos++;break; case'G':putchar(a[pos]);putchar('\n');break; case'I': x=Rin(); l=a.length(); for(int i=0;i<x;i++){ do{ch[i]=getchar();} while(ch[i]=='\n'); rch[x-i-1]=ch[i]; } ch[x]=rch[x]='\0'; a.insert(pos,ch); b.insert(l-pos,rch); break; case'D': x=Rin(); l=a.length(); a.erase(pos,x); b.erase(l-pos-x,x); break; case'R': x=Rin(); l=a.length(); tmp=a.substr(pos,x); a=a.substr(0,pos)+b.substr(l-pos-x,x)+a.substr(pos+x,l-pos-x); b=b.substr(0,l-pos-x)+tmp+b.substr(l-pos,pos); break; } } return 0; }