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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

jzoj4025-找回密码【后缀自动机】

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj4025-找回密码【后缀自动机】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


大意

一個字符串,要求第k小的子串。


解題思路

先建立一個后綴自動機,然后用一個numinum_inumi?表示第iii個節點的可以到達的點所表示的子串總和,然后從第1號點開始查找,判斷一下找到第k小所在的節點后,然后查找輸出。


代碼

#include<cstdio> #include<algorithm> #include<cstring> #define N 200010 #define Get(W) W>='a'?W-71:W-'A' #define fuGet(W) W>=26?W+71:W+'A' using namespace std; int l,last,fail[N],next[N][56],tot,len[N],num[N]; int ls[N],v[N],head,tail,q[N]; long long sum; char s[100001]; int New(int x,int y){next[x][y]=++tot;len[tot]=len[x]+1; } void bfs() {head=0;q[1]=1;tail=1;v[1]=1;do{int x=q[++head];for (int i=0;i<52;i++)if (next[x][i]&&!v[next[x][i]]){v[next[x][i]]=1;q[++tail]=next[x][i];//建立順序}}while (head<tail);for (;tail;tail--){int x=q[tail];for (int i=0;i<52;i++)if (next[x][i]){ls[x]=i;num[x]+=num[next[x][i]]+1;//按順序計算答案}} } void Get_answer() {int x=1;while (sum){if (!ls[x]&&!next[x][0])break;for (int i=0;i<=ls[x];i++)if (next[x][i]){if (num[next[x][i]]+1>=sum||i==ls[x])//在當前節點的搜索樹中{printf("%c",fuGet(i));int y=next[x][i];sum--;if (sum) x=y;//進入該節點break;}else sum-=num[next[x][i]]+1;//跳轉下一棵}} } int main() {scanf("%s",s);scanf("%lld",&sum);l=strlen(s);last=1;len[1]=0;fail[1]=0;tot=1;for (int i=0;i<l;i++){int addc=Get(s[i]);int k=last,j=0;New(last,addc);//新建節點last=tot;for (j=fail[k];j;j=fail[j])if (!next[j][addc])next[j][addc]=last;//直接連接else{int z=next[j][addc];if (len[z]==len[j]+1)fail[last]=z;//連接else{New(j,addc);for (int l=0;l<52;l++)next[tot][l]=next[z][l];//繼承指針fail[tot]=fail[z];fail[z]=fail[last]=tot;//繼承for (int l=j;l;l=fail[l])if (next[l][addc]==z) next[l][addc]=tot;//繼承連接}break;}if (!j) fail[last]=1;/特判}bfs();//計算numGet_answer(); }

總結

以上是生活随笔為你收集整理的jzoj4025-找回密码【后缀自动机】的全部內容,希望文章能夠幫你解決所遇到的問題。

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