BZOJ 2085 [Poi2010]ハムスター(KMP、フロイド、乗算)

アレイは、小さな破滅彼の人生を開く......

トピックへのリンク:https://www.lydsy.com/JudgeOnline/problem.php?id=2085

解決策:この問題に対するこの問題の解決多くのオンラインACオートマトンの各遷移の息子は、間違っています。データをハック:文字列全体を、飛び出すことはありません

個人的に私はACオートマトンは、他の方法で行うことができることを感じるが、試していません

KMP(又はハッシュ)、\(F [I] [J] \)を表し\(Iは\)終了接続\(J \)を直接同時に最長KMPによって決定必要な文字の数、\(J \を)文字列とプレフィックス\(私は\)文字列のサフィックス文字列へ

そして、探しに行く((M-1)\ \ ) 乗算フロイドの最短手順

ないマルチ文字列マッチングAC自動機を使用する必要があります!でも正しさを考慮せずに、ACオートマトントライ木サイズも必ずしも速くKMPよりも、複雑で複数の文字セットであってもよいし、合理的な選択でなければなりません!

コード

KMP:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
using namespace std;

const int N = 200;
const int S = 26;
const int L = 1e5+1e3;
const int LGM = 30;
const llong INF = 1e17;
llong f[N+3][N+3],g[N+3][N+3],g0[N+3][N+3];
char a[L+3];
int nxt[L+3];
int len[L+3];
int slen[L+3];
int n; llong m;

void update(llong &x,llong y) {x = min(x,y);}

int KMP(char str1[],char str2[],int len1,int len2)
{
    for(int i=0; i<=len1; i++) nxt[i] = 0;
    for(int i=2; i<=len1; i++)
    {
        nxt[i] = nxt[i-1];
        while(nxt[i]!=0 && str1[i]!=str1[nxt[i]+1])
        {
            nxt[i] = nxt[nxt[i]];
        }
        if(str1[i]==str1[nxt[i]+1]) nxt[i]++;
    }
    if(str1==str2)
    {
        return len1-nxt[len1];
    }
    else
    {
        int j = 0;
        for(int i=1; i<=len2; i++)
        {
            while(j && str1[j+1]!=str2[i])
            {
                j = nxt[j];
            }
            if(j<len1 && str1[j+1]==str2[i]) j++;
        }
        return len1-j;
    }
}

int main()
{
    scanf("%d%lld",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",a+slen[i-1]+1); len[i] = strlen(a+slen[i-1]+1); slen[i] = slen[i-1]+len[i]+1; a[slen[i]] = ' ';
    }
    for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}
    for(int i=1; i<=n; i++) f[i][i] = len[i];
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            g0[j][i] = KMP(a+slen[i-1],a+slen[j-1],len[i],len[j]);
        }
    }
    /*
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            printf("g0: %d %d %lld\n",i,j,g0[i][j]);
        }
    }
    */
    m--;
    while(m>0)
    {
        if(m&1)
        {
            for(int k=1; k<=n; k++)
            {
                for(int i=1; i<=n; i++)
                {
                    for(int j=1; j<=n; j++)
                    {
                        update(g[i][j],f[i][k]+g0[k][j]);
                    }
                }
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    f[i][j] = g[i][j];
                    g[i][j] = INF;
                }
            }
        }
        for(int k=1; k<=n; k++)
        {
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    update(g[i][j],g0[i][k]+g0[k][j]);
                }
            }
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                g0[i][j] = g[i][j];
                g[i][j] = INF;
            }
        }
        m>>=1;
    }
    llong ans = INF;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            ans = min(ans,f[i][j]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

ACオートマトンコードWA + TLE

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#define llong long long
using namespace std;

const int N = 200;
const int S = 26;
const int L = 1e5+1;
const int LGM = 30;
const llong INF = 1e17;
void update(llong &x,llong y) {x = min(x,y);}
llong g0[N+3][N+3],g[N+3][N+3],f[N+3][N+3];
int len[N+3];
int fail[L+3];
int son[L+3][S+3];
int idpos[N+3];
char a[L+3];
int id[L+3];
int que[L+3];
int dep[L+3];
int n,rtn,siz; llong m;

void insertstr(char str[],int sid)
{
    int u = rtn;
    for(int i=1; i<=len[sid]; i++)
    {
        if(son[u][str[i]])
        {
            u = son[u][str[i]];
        }
        else
        {
            siz++; son[u][str[i]] = siz;
            u = siz;
        }
    }
    id[u] = sid;
    idpos[sid] = u;
}

void add(int u,int v,llong w)
{
    update(g0[id[u]][id[v]],w);
}

void getfail()
{
    int head = 1,tail = 0;
    for(int i=1; i<=S; i++)
    {
        int v = son[rtn][i];
        if(v)
        {
            tail++; que[tail] = v;
            fail[v] = rtn;
        }
    }
    while(head<=tail)
    {
        int u = que[head]; head++;
        for(int i=1; i<=S; i++)
        {
            int v = son[u][i];
            if(v) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = v;}
            else {son[u][i] = son[fail[u]][i];}
        }
    }
}

void bfs(int s)
{
    printf("bfs(%d)\n",s);
    for(int i=1; i<=siz; i++) dep[i] = 0;
    int head = 1,tail = 1; que[1] = s;
    while(head<=tail)
    {
        int u = que[head]; head++;
        int v = fail[i];
        for(int i=1; i<=S; i++)
        {
            v = son[u][i];
            if(v && dep[v]==0)
            {
                dep[v] = dep[u]+1;
                add(s,v,dep[v]);
                tail++; que[tail] = v;
            }
        }
    }
}

int main()
{
    scanf("%d%lld",&n,&m); rtn = siz = 0;
    for(int i=1; i<=n; i++)
    {
        scanf("%s",a+1); len[i] = strlen(a+1);
        for(int j=1; j<=len[i]; j++) a[j] -= 96;
        insertstr(a,i);
    }
    getfail();
    for(int i=0; i<=siz; i++) printf("AC%d fail%d\n",i,fail[i]);
    for(int i=0; i<=siz; i++) {for(int j=1; j<=S; j++) {if(son[i][j]) {printf("son[%d][%c]=%d\n",i,j+96,son[i][j]);}}}
    for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}
    for(int i=1; i<=n; i++) f[i][i] = 0ll;
    for(int i=1; i<=siz; i++)
    {
        if(id[i])
        {
            bfs(i);
        }
    }
    /*
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            printf("g0: %d %d %lld\n",i,j,g0[i][j]);
        }
    }
    */
    m--;
    while(m>0)
    {
        if(m&1)
        {
            for(int k=1; k<=n; k++)
            {
                for(int i=1; i<=n; i++)
                {
                    for(int j=1; j<=n; j++)
                    {
                        update(g[i][j],f[i][k]+g0[k][j]);
                    }
                }
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    f[i][j] = g[i][j];
                    g[i][j] = INF;
                }
            }
        }
        for(int k=1; k<=n; k++)
        {
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    update(g[i][j],g0[i][k]+g0[k][j]);
                }
            }
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                g0[i][j] = g[i][j];
                g[i][j] = INF;
            }
        }
        m>>=1;
    }
    llong ans = INF;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            ans = min(ans,len[i]+f[i][j]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}
/*
4 11
aaaaaaa
aaaa
aaaaaa
aaaaaaaaaa
*/

おすすめ

転載: www.cnblogs.com/suncongbo/p/11038876.html