HDU6138 Fleet of the Eternal Throne (GSAM)

HDU6138 Fleet of the Eternal Throne

Mean

给定\(n\)个字符串,\(m\)次询问\((m<=100)\),每次询问第\(L\)个字符串和第\(R\)个字符串的所有公共子串中,最长的公共子串,满足其是\(n\)个字符串中任意一个的前缀,输出其最长的长度。

Sol

GSAM

注意到\(m\)只有100,每次暴力的将询问的\(L\)串和\(R\)串建出广义后缀自动机,每个状态记录其在\(L\)串中出现的次数和在\(R\)串中出现的次数\(siz[i][0]和siz[i][1]\),跑一遍\(fail树\),向上传递维护一下。

随后依次遍历\(n\)个字符串,注意不允许失配,因为要求的是前缀。

把所有的合法前缀长度求个\(max\)即可。

复杂度\(O(nm)\).

Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define lowbit(x) (x&(-x))
#define debug(x) cout<<#x<<" :"<<x<<endl
#define debug1(x) cout<<#x<<" :"<<x<<" "
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
const int MAX=10000007;
inline int read() {
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
    return x*f;
}

inline void out(int x) {   
    if(x>9) out(x/10);   
    putchar(x%10+'0'); 
}     
int q[N];
struct Node{
    int len,fa;
    int ch[10];
}node[N*2];
int tot=1,last=1;
int siz[N*2][3];
int extend(int c,int last,int id){
    if(node[last].ch[c]){
        int p = last,x = node[p].ch[c];
        if(node[p].len + 1 == node[x].len){//特判1
            siz[x][id]=1;
            return x;
        }
        else{//特判2
            int y = ++tot;node[y].len = node[p].len+1;
            for(int i=0;i<=9;++i)node[y].ch[i] = node[x].ch[i];
            while(p&&node[p].ch[c]==x)node[p].ch[c]=y,p=node[p].fa;
            node[y].fa=node[x].fa,node[x].fa=y;
            siz[y][id]=1;
            return y;
        }
    }

    int p = last ,np = last = ++tot;
    node[np].len = node[p].len + 1;
    for(;p && !node[p].ch[c]; p = node[p].fa){
        node[p].ch[c] = np;
    }
    if(!p)node[np].fa = 1;
    else{
        int q = node[p].ch[c];
        if(node[q].len == node[p].len + 1){
            node[np].fa = q;
        }
        else{
            int nq = ++tot;
            node[nq] = node[q];
            node[nq].len = node[p].len+1;
            node[q].fa = node[np].fa = nq;
            for(;p && node[p].ch[c] == q;p = node[p].fa){
                node[p].ch[c] = nq;
            }
        }
    }
    siz[last][id]=1;
    return last;

}
void init(){
    rep(i,0,tot){
        rep(j,0,25){
            node[i].ch[j]=0;
        }
        node[i].fa=0;
        siz[i][0]=siz[i][1]=0;
    }
    tot=last=1;
}

int T,n,m;
string s[N];
char p[N];
int in[N*2];
void solve(){
    memset(in,0,sizeof in);
    queue<int>Q;
    rep(i,2,tot){
        in[node[i].fa]++;
    }
    rep(i,1,tot){
        if(!in[i])Q.push(i);
    }
    while(!Q.empty()){
        int x =Q.front();
        Q.pop();
        siz[node[x].fa][0]+=siz[x][0];
        siz[node[x].fa][1]+=siz[x][1];
        if(--in[node[x].fa]==0){
            Q.push(node[x].fa);
        }
    }
    int mx = 0;
    rep(i,1,n){
        int len =s[i].size();
        int now = 1;
        int val = 0;
        rep(j,0,len-1){
            int c = s[i][j]-'a';
            if(node[now].ch[c]){
                now = node[now].ch[c];
                if(siz[now][0]&&siz[now][1]){
                    val = j+1;
                }
            }
            else{
                break;
            }
        }
        mx = max(mx,val);   
    }
    printf("%d\n",mx);
}

int main(){
    T=read();
    while(T--){
        n=read();
        rep(i,1,n){
            scanf("%s",p);
            s[i].clear();
            int len = strlen(p);
            rep(j,0,len-1){
                s[i]+=p[j];
            }
        }
        m=read();
        rep(i,1,m){
            int l,r;
            l=read(),r=read();
            init();
            last = 1;
            for(int j=0,len=s[l].size();j<len;++j){
                last = extend(s[l][j]-'a',last,0);
            }
            last = 1;
            for(int j=0,len=s[r].size();j<len;++j){
                last = extend(s[r][j]-'a',last,1);
            }
            solve();
        }
    }
    return 0;
}
上一篇:USACO 1.6.1 数字三角形


下一篇:认识input输入框的placeholder属性