luoguP2408不同子串個數

2022-05-19 06:28:47 字數 1113 閱讀 9405

可以知道每乙個子串都是字尾的字首,那麼對於第\(i\)小的字尾的貢獻就可以表示為n-sa[i]+1

然而會存在重複的子串,注意height陣列的定義,對於sa[i-1]和sa[i],只有height[i]個子串會被重複計算,每次都減掉就好了

**:

#include#include#includeusing namespace std;

void read(int &x)

#define rg register

const int maxn=1e5+10;long long ans;

int n,a[maxn],m='z',x[maxn],y[maxn],num,sa[maxn],rk[maxn],h[maxn];char p[maxn];

int main()

for(rg int i=1;i<=n;i++)rk[sa[i]]=i;

for(rg int i=1,k=0,j;i<=n;h[rk[i++]]=k)

for(k=k?k-1:k,j=sa[rk[i]-1];p[j+k]==p[i+k];k++);

for(rg int i=1;i<=n;i++)ans+=n-sa[i]-h[i]+1;printf("%lld\n",ans);

}

建出字尾自動機,拓撲排序就行了

**:

#include#include#include#include#includeusing namespace std;

void read(int &x)

#define rg register

const int maxn=5e6+10;

int n,tot,las,pre[maxn],nxt[maxn],h[maxn],cnt,in[maxn];

char a[maxn];

long long ans,f[maxn];

struct sams[maxn];

void sam_pre()

void ins(int x)

} las=cur;

}void add(int x,int y)

void top_sort() }}

int main()

luogu P2408 不同子串個數

考慮反向操作,去計算有多少組相同的子串,對於一組大小為k的極大相同子串的集合,ans k 1。為了避免重複計算,需要一種有效的,有順序的記錄方案。比如說,對於每乙個相同組,按其起始點所在的位置排序,對於除了第乙個串以外的串,均記 1的貢獻。但這種東西是非常難以快速統計的。但是,可以對於每乙個相同組,...

LuoguP2408 不同子串個數(字尾自動機)

題目傳送門 先建好字尾自動機,然後答案就是 sum len u len link u 為什麼這樣是對的?每個狀態所代表的字串是沒有交集的,所以我們只需求出每個狀態有多少個子串。其實在學習構建sam的時候我們學過link的乙個性質,就是len link x 1 min len x 且乙個狀態內的字串按...

P2408 不同子串個數 SA LCP SAM

傳送門 經典的sa lc psa lcp sa lcp 題目。顯然所有子串數目為n n 1 2 dfrac 2n n 1 因此我們只需知道重複的子串有多少個。根據l cp lcplc p我們知道利用lcp lcplc p求出的hei ght i l cp i i 1 即排 名第i名 和第i 1名的最...