可以知道每乙個子串都是字尾的字首,那麼對於第\(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名的最...