題目大意:
給出乙個長度為n的字串t(n<=5e5),有m次詢問(m<=5e5)
每次詢問有兩個操作
1. 給出排名k1,k2,詢問字典序排名為k1的子串的下標l,r
如果該子串和字串t的其它子串相同,那麼輸出起始位置第k2小的子串的下標l,r
2. 給出子串下標l,r,問該子串在t的所有不同子串中的字典序排名k1以及該子串在所有字 符串t的子串且與其相同的子串中的起始位置排名k2
做法:首先建立字串t的字尾陣列,算出其height陣列,rank陣列以及sa陣列
對於第一種操作,我們可以通過算所有字尾字串的不同子串的貢獻度,可以預處理出以等級i開頭的不同子串數量的字首和,通過二分可以確定出子串所在的等級和長度,然後兩次二分確定出等級區間,最後通過主席樹得出答案.
對於第二種操作,查詢為l,r.我們先看rank[l],即l開始的字尾的排名,然後設p=rank[l],利用線段樹區間查詢求出p的左側第乙個height值小於r-l+1的值的下標pl,再利用線段樹區間查詢求出p的右側第乙個height值小於r-l+1的值的下標pr.設兩個下標分別為pl,pr,那麼區間[pl+1,pr-1]中的字尾都有乙個共同點,他們的公共字首肯定包含子串[l,r],用第一種操作的字首和,子串長度,height陣列可得出k1,再用主席樹二分進行操作得出詢問的子串在與其相同的子串中的起始位置排名k2即可.
**:
#includeusing namespace std;#include#include#include#include#includeconst long long maxn=500010;
long long t1[maxn],t2[maxn],c[maxn];
bool cmp(long long *r,long long a,long long b,long long i)
void da(char str,long long sa,long long rankp,long long height,long long n,long long m)
long long k=0;
n--;
for (i=0;i<=n;i++) rankp[sa[i]]=i;
for (i=0;i=r)
int mid = (l+r)/2;
create(k*2,l,mid);
create(k*2+1,mid+1,r);
a[k] = min(a[k*2],a[k*2+1]);
} int queryl(int k,int p,int s)
void insert(int l,int r,int &now,int pre,int x)
int query(int l,int r,int x,int y,int k)
int root[maxn],ass[maxn];
pairgetpos(int k1,int n)else if(v[ans-1]>l)
rr = mid - 1;
else
ll = mid + 1;
}printf("%lld %lld\n",ans1,ans2);
} }return 0;
}
4322 字串遊戲(strgame)
題意 記憶體限制 256 mib 時間限制 1000 ms pure和dirty決定玩 t tt 局遊戲。對於每一局遊戲,有 n nn 個字串,並且每一局遊戲由 k kk 輪組成。具體規則如下 在每一輪遊戲中,最開始有乙個空串,兩者輪流向串的末尾新增乙個字元,並且需要保證該串為 n nn 個字串中任...
bzoj 2121 字串遊戲
題目大意 給你乙個大字串和乙個字串的集合,每次可以從字串的集合中選出乙個,如果那個大字串中包含了這個字串,就可以從大串中將小串刪掉,刪完後兩邊接起來,求刪完後大串最少剩幾個字元 大串 150,小串 20,小串個數 30 這題沒想著怎麼做,主要還是太弱了。首先可以設f i j k l 代表第i個到第j...
bzoj 2121 字串遊戲
bx正在進行乙個字串遊戲,他手上有乙個字串l,以及其他一些字串的集合s,然後他可以進行以下操作 對於乙個在集合s中的字串p,如果p在l中出現,bx就可以選擇是否將其刪除,如果刪除,則將刪除後l 成的左右兩部分合併。舉個例子,l abcdefg s 如果bx選擇將 de 從l中刪去,則刪後的l abc...