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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SPOJ7258--SUBLEX(SAM)

發(fā)布時間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SPOJ7258--SUBLEX(SAM) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉(zhuǎn)載請注明出處,謝謝 http://blog.csdn.net/ACM_cxlove?viewmode=contents ??? by---cxlove??

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

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

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

首先以每個結(jié)點為終態(tài)算一個子串,所以初始化計數(shù)為1。

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

SPOJ很卡時,需要各種優(yōu)化,首先是經(jīng)典的拓撲。

一次預(yù)處理,把后繼全部存好,以為相應(yīng)的字母。

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

?

#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; }

?

自己的代碼:

#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 90080 #define LL long long int char str[maxn],ans[maxn]; int pos = 0; struct SAM {SAM *pre,*son[26];int len,sonnum,Son[26];char ch[26];LL g; }que[maxn<<1],*root,*tail,*b[maxn<<1]; int tot; int C[maxn<<1]; void add(int c,int l) {SAM *p=tail,*np=&que[tot++];np->len=l; tail=np;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;}} }void init(int n) {tot = 0;pos = 0;/*for(int i = 0;i < n;i++){que[i].g = 0; que[i].pre = NULL; que[i].sonnum = 0;for(int j = 0;j < 26;j++) {que[i].son[j] = NULL;}memset(que[i].son,0,sizeof(que[i].son));}*/root = tail = &que[tot++];//memset(C,0,sizeof(C)); }inline int max(int a,int b) {return a>b?a:b; }void dfs(SAM * now,int k) {if(k == 0) return;for(int i = 0;i < now -> sonnum;i++){if(now -> son[now -> Son[i]] -> g >= k){ans[pos++] = now -> ch[i];dfs(now -> son[now ->Son[i]],k-1);return;}else k -= now -> son[now -> Son[i]] -> g;} }int main() {//freopen("in.txt","r",stdin);scanf("%s",str);int len = strlen(str);init(len << 1);/for(int i = 0;i < len;i++){add(str[i] - 'a',i + 1);}//for(int i = 0;i < tot;i++) C[que[i].len]++;///for(int i = 1;i <= len;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].g = 1;///for(int i = tot-1;i >= 0;i--){for(int j = 0;j < 26;j++){if(b[i]->son[j]) {b[i] -> Son[b[i]->sonnum] = j;b[i] -> ch[b[i]->sonnum] = j+'a';b[i] -> sonnum++;b[i] -> g += b[i] -> son[j] -> g;}}}/int q;scanf("%d",&q);while(q--){int k;scanf("%d",&k);pos = 0;dfs(&que[0],k);ans[pos++] = '\0';printf("%s\n",ans);}return 0; }


?


#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 90080 #define LL long long int char str[maxn],ans[maxn]; int pos = 0; struct SAM {SAM *pre,*son[26];int len,sonnum,Son[26];char ch[26];LL g; }que[maxn<<1],*root,*tail,*b[maxn<<1]; int tot; int C[maxn<<1]; void add(int c,int l) {SAM *p=tail,*np=&que[tot++];np->len=l; tail=np;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;}} }void init(int n) {tot = 0;pos = 0;/*for(int i = 0;i < n;i++){que[i].g = 0; que[i].pre = NULL; que[i].sonnum = 0;for(int j = 0;j < 26;j++) {que[i].son[j] = NULL;}memset(que[i].son,0,sizeof(que[i].son));}*/root = tail = &que[tot++];//memset(C,0,sizeof(C)); }inline int max(int a,int b) {return a>b?a:b; }void dfs(SAM * now,int k) {if(k == 0) return;for(int i = 0;i < now -> sonnum;i++){if(now -> son[now -> Son[i]] -> g >= k){ans[pos++] = now -> ch[i];dfs(now -> son[now ->Son[i]],k-1);return;}else k -= now -> son[now -> Son[i]] -> g;} }int main() {//freopen("in.txt","r",stdin);scanf("%s",str);int len = strlen(str);init(len << 1);/for(int i = 0;i < len;i++){add(str[i] - 'a',i + 1);}//for(int i = 0;i < tot;i++) C[que[i].len]++;///for(int i = 1;i <= len;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].g = 1;///for(int i = tot-1;i >= 0;i--){for(int j = 0;j < 26;j++){if(b[i]->son[j]) {b[i] -> Son[b[i]->sonnum] = j;b[i] -> ch[b[i]->sonnum] = j+'a';b[i] -> sonnum++;b[i] -> g += b[i] -> son[j] -> g;}}}/int q;scanf("%d",&q);while(q--){int k;scanf("%d",&k);pos = 0;dfs(&que[0],k);ans[pos++] = '\0';printf("%s\n",ans);}return 0; }


?


?

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。