您的位置:首页 > 其它

SAM(后缀自动机)模板

2017-12-27 21:32 477 查看
个人感觉这个SAM比SA要难理解的多,两者好像功能有相似之处,不过SAM在一些题目上有它的优势

把板子和模板题记录下来,方便以后抄标

学习小记

模板题:【GDOI2012】字符串

Description

mmm正在学习字典序。现在老师给她布置了一个作业:给出一个字符串,问该字符串的所有不同的子串中,按字典序排第K的字串。由于众所周知的原因,mmm需要你为她解决这个问题。

Input

第1行输入一个只有小写字母组成的字符串。

第2行输入N,为询问个数。

第3到N+2行每行输入一个整数Ki。

Output

输出N行,第i行输出按字典序排第Ki的子串,如果Ki超出了子串数量,输出-1.

Sample Input

abbb

8

1

2

3

4

5

6

7

8

Sample Output

a

ab

abb

abbb

b

bb

bbb

-1

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 20100
using namespace std;
char s
;
int n,last=1,tot=1,a
,b[N*10],q,sum[N*10];
struct SAM{
int len,size,fail;
int to[26];
}t[N*10];
void add(int x)
{
int p=last,np=++tot;
t[np].len=t[p].len+1;t[np].size=1;last=np;
for(;p&&t[p].to[x]==0;p=t[p].fail) t[p].to[x]=np;
if(p==0){t[np].fail=1;return;}
int q=t[p].to[x];
if(t[p].len+1==t[q].len) t[np].fail=q;
else
{
int nq=++tot;t[nq]=t[q];
t[nq].len=t[p].len+1;t[q].fail=t[np].fail=nq;
for(;p&&t[p].to[x]==q;p=t[p].fail) t[p].to[x]=nq;
}
}
void ssort()
{
fo(i,1,tot) a[t[i].len]++;
fo(i,1,n) a[i]+=a[i-1];
fd(i,tot,1) b[a[t[i].len]--]=i;
}
void bfs(int k)
{
int x=1;
while(k>t[x].size)
{
k-=t[x].size;
fo(i,0,25)
if(t[x].to[i]>0)
{
if(sum[t[x].to[i]]>=k)
{
x=t[x].to[i];
putchar(i+97);
break;
}
k-=sum[t[x].to[i]];
}
}
putchar('\n');
}
int main()
{
scanf("%s\n",s+1);n=strlen(s+1);
fo(i,1,n) add(s[i]-97);
ssort();
fd(i,tot,1)
{
int x=b[i];sum[x]=t[x].size;
fo(i,0,25) sum[x]+=sum[t[x].to[i]];
}
scanf("%d",&q);
while(q--)
{
int k;scanf("%d",&k);
if(k>sum[1]) {printf("-1\n");continue;}
bfs(k);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: