New Distinct Substrings(后缀数组)
生活随笔
收集整理的這篇文章主要介紹了
New Distinct Substrings(后缀数组)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
New Distinct Substrings(后綴數(shù)組)
給定一個(gè)字符串,求不相同的子串的個(gè)數(shù)。\(n<=50005\)。
顯然,任何一個(gè)子串一定是后綴上的前綴。先(按套路)把后綴排好序,對于當(dāng)前的后綴\(S_i\),顯然他有\(n-sa[i]\)個(gè)前綴。其中,有\(height[i]\)個(gè)前綴字符串在編號(hào)比它小的后綴中出現(xiàn)過,因此它對答案的貢獻(xiàn)是\(n-sa[i]-height[i]\)。
#include <cstdio> #include <cstring> using namespace std;const int maxn=50005; int T, n, m=maxn; char s[maxn];bool cmp(int *r, int a, int b, int j){return r[a]==r[b]&&r[a+j]==r[b+j]; } int *x, *y, *t, wa[maxn], wb[maxn], ws[maxn], sa[maxn], wv[maxn], ht[maxn]; void Suffixsort(char *r){int i, j, p=0; x=wa, y=wb; m=maxn;for (i=0; i<m; ++i) ws[i]=0;for (i=0; i<n; ++i) ++ws[x[i]=r[i]];for (i=1; i<m; ++i) ws[i]+=ws[i-1];for (i=0; i<n; ++i) sa[--ws[r[i]]]=i;for (j=1; p<n&&j<n; j<<=1, m=p+1){for (p=0, i=n-j; i<n; ++i) y[p++]=i;for (i=0; i<n; ++i) if (sa[i]>=j) y[p++]=sa[i]-j;for (i=0; i<n; ++i) wv[i]=x[y[i]];for (i=0; i<m; ++i) ws[i]=0;for (i=0; i<n; ++i) ++ws[x[i]];for (i=1; i<m; ++i) ws[i]+=ws[i-1];for (i=n-1; i>0; --i) sa[--ws[wv[i]]]=y[i]; //這句話依然是背下來的t=x; x=y; y=t; x[sa[0]]=1;for (p=1, i=1; i<n; ++i) x[sa[i]]=cmp(y, sa[i-1], sa[i], j)?p:++p; //+1 }memset(ht, 0, sizeof(ht));for (int i=0; i<n; ++i) --x[i]; p=0;for (int i=0; i<n; ht[x[i++]]=p){if (!x[i]) continue;for (p?p--:0, j=sa[x[i]-1]; r[i+p]==r[j+p]&&i+p<n; ++p);} ht[0]=0;return; }int main(){scanf("%d", &T); int ans;while (T--) {scanf("%s", s); n=strlen(s); Suffixsort(s); ans=0;//for (int i=0; i<n; ++i) printf("%d ", sa[i]); puts("");//for (int i=1; i<n; ++i) printf("%d ", ht[i]);for (int i=0; i<n; ++i) ans+=n-sa[i]-ht[i];printf("%d\n", ans);}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/MyNameIsPc/p/9177830.html
總結(jié)
以上是生活随笔為你收集整理的New Distinct Substrings(后缀数组)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英雄联盟猴子的问题
- 下一篇: 极米H3如何退出儿童模式