日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

后缀数组 --- HDU 3518 Boring counting

發布時間:2025/3/17 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后缀数组 --- HDU 3518 Boring counting 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?Boring counting

Problem's Link: ??http://acm.hdu.edu.cn/showproblem.php?pid=3518


?

Mean:?

給你一個字符串,求:至少出現了兩次(無重疊)的子串的種類數。

analyse:

后綴數組中height數組的運用,一般這個數組用得很少。

總體思路:分組統計的思想:將相同前綴的后綴分在一個組,然后對于1到len/2的每一個固定長度進行統計ans。

首先我們先求一遍后綴數組,并把height數組求出來。height數組代表的含義是:字典序相鄰(即rank數組相鄰)的兩個后綴的最長公共前綴的長度。

由于子串不能重疊,那么就可以確定出子串長度的取值范圍:1~len/2。(維護sa[]的最大值和最小值是為了判斷排名相鄰兩個字符串的距離是否大于k,只有大于k才能保證不重疊)。

接下來我們對1~len/2的每一個固定長度進行統計該長度的子串有多少種,一路累加即得答案。

關鍵是要理解使用height數組進行分組統計的過程。

Time complexity: O(nlogn)

?

Source code:?

/* * this code is made by crazyacking * Verdict: Accepted * Submission Date: 2015-05-09-21.22 * Time: 0MS * Memory: 137KB */ #include <queue> #include <cstdio> #include <set> #include <string> #include <stack> #include <cmath> #include <climits> #include <map> #include <cstdlib> #include <iostream> #include <vector> #include <algorithm> #include <cstring> #define LL long long #define ULL unsigned long long using namespace std; const int MAXN=1010; //以下為倍增算法求后綴數組 int wa[MAXN],wb[MAXN],wv[MAXN],Ws[MAXN]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} void da(const char *r,int *sa,int n,int m) // {int i,j,p,*x=wa,*y=wb,*t;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=n-1;i>=0;i--) sa[--Ws[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){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[wv[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];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;}return; } int sa[MAXN],Rank[MAXN],height[MAXN]; //求height數組 void calheight(const char *r,int *sa,int n){int i,j,k=0;for(i=1;i<=n;i++) Rank[sa[i]]=i;for(i=0;i<n;height[Rank[i++]]=k)for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);return; } char str[MAXN]; int solve(int k,int len) {int maxx=0,minn=INT_MAX,ans=0;for(int i=1;i<=len;++i){if(height[i]>=k)maxx=max(maxx,max(sa[i-1],sa[i])),minn=min(minn,min(sa[i-1],sa[i]));else{if(maxx-minn>=k) ans++;maxx=0,minn=INT_MAX;}}if(maxx-minn>=k)ans++;return ans; } int main() {while(~scanf("%s",str) && strcmp(str,"#")!=0){int len=strlen(str);/**< 傳入參數:str,sa,len+1,ASCII_MAX+1 */da(str,sa,len+1,130);/**< str,sa,len */calheight(str,sa,len);LL ans=0;for(int i=1;i<=len/2;++i)ans+=solve(i,len);cout<<ans<<endl;}return 0; } View Code

?

轉載于:https://www.cnblogs.com/crazyacking/p/4490844.html

新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的后缀数组 --- HDU 3518 Boring counting的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。