smoj2010(广义后缀自动机)

来源:互联网 发布:阿里云怎么打开iis 编辑:程序博客网 时间:2024/05/16 10:02

这是我在比赛时唯一会做的题,终于让我觉得学SAM有点用了,毕竟复杂度就是优。(传说题解后缀数组还要n^2)(话说SAM不比KMP难打吧)

题面
这里写图片描述

在SAM中,某个串出现的次数为该串所属状态的Right集大小,这题虽然朴素的建好SAM就能做,但是判断有点烦。
我突然想到了某次与dalao的对话:
dalao:什么题正解sam,后缀数组只有35分?(这两个不是一样的东西吗)
わだし:《sam在trie上的拓展…》

根据我粗鄙的理解,对一个trie能建成一棵广义sam,与普通sam的区别之一就是Right集的元素是trie上的结点。
凭借这个粗鄙的理解,就可以做了。

本题中两个串构成一个trie,trie上的结点可能是s1的或者是s2的。根据题意,就是某个状态的Right集中,仅有一个结点是s1串的,仅有一个是s2的,该状态的Min与Max就能贡献答案。

#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=100100;char cc[N];int len,last=1,cnt=1;int son[N][26],pre[N],dep[N],f[N],r[N][2];int ans1=123456,ans2;struct yy{    int d,num;}b[N];bool cmp(yy x,yy y){    return x.d<y.d;}void insert(int x,int ops){    dep[++cnt]=dep[last]+1;    int np=cnt,p=last;    last=cnt;    r[np][ops]=1;    for(;!son[p][x];p=pre[p])    son[p][x]=np;    if(!p)    pre[np]=1;    else    {        int q=son[p][x];        if(dep[q]==dep[p]+1)        pre[np]=q;        else        {            dep[++cnt]=dep[p]+1;            int nq=cnt;            mmcp(son[nq],son[q]);            pre[nq]=pre[q];            pre[q]=pre[np]=nq;            for(;son[p][x]==q;p=pre[p])            son[p][x]=nq;        }    }}int main(){    scanf("%s",cc);    len=strlen(cc);    for(int i=0;i<len;i++)    insert(cc[i]-'a',0);    last=1;    scanf("%s",cc);    len=strlen(cc);    for(int i=0;i<len;i++)    insert(cc[i]-'a',1);    for(int i=1;i<=cnt;i++)    {        b[i].d=dep[i];        b[i].num=i;    }    sort(b+1,b+cnt+1,cmp);    for(int i=cnt;i>=1;i--)    {        r[pre[b[i].num]][0]+=r[b[i].num][0];        r[pre[b[i].num]][1]+=r[b[i].num][1];    }    for(int i=2;i<=cnt;i++)    if(r[i][0]==1&&r[i][1]==1)    {        ans1=min(ans1,dep[pre[i]]+1);        ans2=max(ans2,dep[i]);    }    if(ans1==123456)    cout<<"-1 -1"<<endl;    else     cout<<ans1<<" "<<ans2<<endl;    return 0;}
原创粉丝点击