題意:給出乙個長度到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 個,這個後面解釋,於是把沒有分支並且不是字尾節點的點壓縮到一起,就變成了字尾樹。不難發現,字尾樹可以表示該字串的所有子串。下面分析一下...