CF427D 【Match and Catch】

tag:SAM


提供一种不用广义\(SAM\)的做法

\(s\)\(SAM\),然后用\(t\)去跑匹配,对于当前\(i\),匹配到的节点为\(cur\),匹配长度为\(nowlen\)

  • \(cur\)不是\(SAM\)\(parent\)树叶子节点,则continue
  • 否则说明\(t\)\(len\in[len(fa(cur))+1,nowlen]\)\(r=i\)的这些子串都满足同时在两个串中出现,且在\(s\)中仅出现一次

然后对于\(t\)再建\(SAM\),对于当前\(i\)\(SAM\)树上对应节点为\(pos\)

  • \(pos\)不是\(SAM\)\(parent\)树叶子节点,则continue
  • 否则说明\(t\)\(len\in[len(fa(pos))+1,len(pos)],r=i\)的这些子串都满足\(t\)中仅出现一次

然后对于每个\(r\)都可以求出对应的满足条件的\(len\)的区间(即上面两个区间的交),然后取最小\(len\)更新答案

#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
    char ch; bool flag=false;
    while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
    for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
    if(flag)n=-n;
}

const int MAXN = 5005;

struct SAM{
    struct node{
        int son[26], fa, len;
        #define son(x,opt) t[x].son[opt]
        #define fa(x) t[x].fa
        #define len(x) t[x].len
    }t[MAXN<<1];
    int node_cnt=1, prv=1;

    inline int insert(int v){
        int x = ++node_cnt; len(x) = len(prv)+1;
        while(prv and !son(prv,v)) son(prv,v) = x, prv = fa(prv);
        if(!prv) fa(x) = 1;
        else{
            int p = son(prv,v);
            if(len(p) == len(prv)+1) fa(x) = p;
            else{
                int new_p = ++node_cnt; len(new_p) = len(prv)+1;
                fa(new_p) = fa(p); fa(p) = fa(x) = new_p;
                copy(t[p].son,t[p].son+26,t[new_p].son);
                while(prv and son(prv,v)==p) son(prv,v) = new_p, prv = fa(prv);
            }
        }
        return prv=x;
    }

    char mk[MAXN<<1];
    inline void Unique(){for(register int i=1; i<=node_cnt; i++) mk[fa(i)] = true;}
}S,T;

char a[MAXN];
int pos[MAXN];

int main(){
    scanf("%s",a+1); int n = strlen(a+1);
    for(register int i=1; i<=n; i++) S.insert(a[i]-'a'); S.Unique();
    scanf("%s",a+1); n = strlen(a+1);
    for(register int i=1; i<=n; i++) pos[i] = T.insert(a[i]-'a'); T.Unique();
    int ans = INT_MAX;
    for(register int i=1, cur=1, len=0; i<=n; i++){
        while(cur and !S.son(cur,a[i]-'a')) cur = S.fa(cur), len = S.len(cur);
        if(!cur) cur = 1, len = 0;
        else{
            cur = S.son(cur,a[i]-'a'), len++;
            if(S.mk[cur] or T.mk[pos[i]]) continue;
            if(len <= T.len(T.fa(pos[i]))) continue;
            if(T.len(pos[i]) <= S.len(S.fa(cur))) continue;
            ans = min(ans,max(S.len(S.fa(cur))+1,T.len(T.fa(pos[i]))+1));
        }
    }
    cout<<(ans==INT_MAX?-1:ans)<<endl;
    return 0;
}
posted @ 2021-07-01 15:15  oisdoaiu  阅读(33)  评论(0编辑  收藏  举报