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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

SPOJ 7258 SUBLEX (SAM)

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SPOJ 7258 SUBLEX (SAM) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請注明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents??? by---cxlove ??

題目:給出一個串,查詢字典序排在第k個的是哪個子串

http://www.spoj.pl/problems/SUBLEX/?

由于SAM能遍歷所有的子串,只要預處理出某個結點的后繼中有多少個不同的子串就可以了。

首先以每個結點為終態算一個子串,所以初始化計數為1。

然后按照拓撲序,用后繼更新pre。類似數DP那種。

SPOJ很卡時,需要各種優化,首先是經典的拓撲。

一次預處理,把后繼全部存好,以為相應的字母。

有個地方需要注意,在查詢的時候,有個k--。因為以當前字母結束也是一個子串,所以需要減掉

#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<string> #include<queue> #define inf 100000005 #define M 40 #define N 200015 #define maxn 300005 #define eps 1e-10 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define LL unsigned long long #define MOD 1000000007 #define lson step<<1 #define rson step<<1|1 #define sqr(a) ((double)(a)*(a)) #define Key_value ch[ch[root][1]][0] #define test puts("OK"); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; struct SAM {SAM *pre,*son[26];int len,cnt; }*root,*tail,que[N],*b[N]; char str[N/2]; int son[N][26],cnt[N]; int tot=0; int c[N]; char ch[N][26]; void add(int c,int l) {SAM *p=tail,*np=&que[tot++];np->len=l;while(p&&p->son[c]==NULL) p->son[c]=np,p=p->pre;if(p==NULL) np->pre=root;else{SAM *q=p->son[c];if(p->len+1==q->len) np->pre=q;else{SAM *nq=&que[tot++];*nq=*q;nq->len=p->len+1;np->pre=q->pre=nq;while(p&&p->son[c]==q) p->son[c]=nq,p=p->pre;}}tail=np; } void slove(int k) {int l=0;int now=0;while(k){for(int i=0;i<cnt[now];i++){if(k>que[son[now][i]].cnt){k-=que[son[now][i]].cnt;}else{str[l++]=ch[now][i];now=son[now][i];k--;break;}}}str[l]='\0';puts(str); } int main() {root=tail=&que[tot++];scanf("%s",str);int l=strlen(str);for(int i=0;str[i];i++) add(str[i]-'a',i+1);for(int i=0;i<tot;i++) c[que[i].len]++;for(int i=1;i<tot;i++) c[i]+=c[i-1];for(int i=0;i<tot;i++) b[--c[que[i].len]]=&que[i];for(int i=0;i<tot;i++) que[i].cnt=1;for(int i=tot-1;i>=0;i--){SAM *p=b[i];for(int j=0;j<26;j++){if(p->son[j]){int u=p-que,v=p->son[j]-que;son[u][cnt[u]]=v;ch[u][cnt[u]++]=j+'a';p->cnt+=p->son[j]->cnt;}}}int q,k;scanf("%d",&q);while(q--){scanf("%d",&k);slove(k);}return 0; }

總結

以上是生活随笔為你收集整理的SPOJ 7258 SUBLEX (SAM)的全部內容,希望文章能夠幫你解決所遇到的問題。

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