hdu5008 字尾陣列 線段樹

2021-06-25 16:38:45 字數 1806 閱讀 4109

題意:給出乙個長度到10^6的串 現在要統計該串中第k小的不重複子串

然後找到最左端的那個 

解法:字尾陣列的作用是統計每個左端點不重複的串的個數

然後用線段樹維護每個起始點的不重複子串綜合

那麼就可以求出第k個子串所在的塊了

然後就是求再這個塊中出現的最早點 這個用二分+rmq

原因很簡單 那就是》=該串長的字尾串會聚集在一起出現

暴力更快 那也就是直接往左右兩邊找sa[i]出現的最小位置 直到height先給出暴力:

#include#include#include#includeusing namespace std;

#define maxn 111111

#define ll long long

#define ls (rt<<1)

#define rs (rt<<1|1)

#define mid ((l+r)>>1)

char str[maxn];

int sa[maxn],no_1[maxn],no_2[maxn],ex[maxn],he[maxn],rk[maxn],n,limi;

int id[25][maxn],pos,len;

ll sum[maxn<<2];

void _sa(char *st)

int q;

ll k;

int main()

else query(1,1,n,k);

if(pos==-1)printf("0 0\n");

else

while(n_r<=n&&he[n_r]>=len)

l=mi+1;r=l+len-1;

printf("%d %d\n",l,r);}}

}return 0;

}

然後是rmq:

#include#include#includeusing namespace std;

#define maxn 111111

typedef long long ll;

#define ls (rt<<1)

#define rs (rt<<1|1)

#define mid ((l+r)>>1)

char txt[maxn];

int sa[maxn],no_1[maxn],no_2[maxn],ex[maxn],he[maxn],rk[maxn],n,limi;

int mi[25][maxn],lg[maxn],id[25][maxn],pos,len;

ll sum[maxn<<2];

void _sa(char *st)

return ans;

}int _r(int x)

return ans;

}void up(int rt)

void build(int rt,int l,int r)

build(ls,l,mid);

build(rs,mid+1,r);

up(rt);

}void query(int rt,int l,int r,ll k)

if(sum[ls]>=k)query(ls,l,mid,k);

else query(rs,mid+1,r,k-sum[ls]);

}int q,x,y;

ll k;

int main()

else query(1,1,n,k);

if(pos==-1)printf("0 0\n");

else}}

return 0;

}

字尾陣列 二分 hdu 5008

大致題意 給出乙個長度小於100000的字串,求字串中字典序排在第k位的子串。大致思路 聯動ural1590 這裡有乙個字尾陣列的基本規律,每個字尾去掉重複的字首之後留下的就是所有的子串。eg字串 aabb 排列成字尾陣列之後,代表height計算出的和sa i 1 相同的部分 sa 1 0 aab...

字尾樹 字尾陣列

在字串處理當中,字尾樹和字尾陣列都是非常有力的工具,其中字尾樹大家了解得比較多,關於字尾陣列則很少見於國內的資料。其實字尾陣列是字尾樹的乙個非 常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽 中字尾...

字尾樹 字尾陣列

我們考慮將乙個串的所有字尾插入乙個trie中,得到的trie就是字尾trie。我們可以發現,樹上有分叉或者是字尾節點的點的個數是o l en o len o len 個,這個後面解釋,於是把沒有分支並且不是字尾節點的點壓縮到一起,就變成了字尾樹。不難發現,字尾樹可以表示該字串的所有子串。下面分析一下...