zoukankan      html  css  js  c++  java
  • ZOJ 3817Chinese Knot(The 2014 ACM-ICPC Asia Mudanjiang Regional First Round)

    思路: 将4个串每个串都反向这样得到新的四个串一共8个串,对于母串每个位置检测这个串能不能放进去,hs或者后缀数组都可以。然后dp[i][j]  (0<i<len  0<=j<8)表示长度为i以第j个串结尾能不能到达,如果能 那么 就可以i+1位置利用原来处理出来的来转移。要注意开头结尾即可。

    注意:以第i个串结尾  那么下个串 就不能用第i个串的反向串。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<time.h>
    #include<string>
    #define REP(i,n) for(int i=0;i<n;++i)
    #define REP1(i,a,b) for(int i=a;i<=b;++i)
    #define REP2(i,a,b) for(int i=a;i>=b;--i)
    #define MP make_pair
    #define LL long long
    #define ULL unsigned long long
    #define X first
    #define Y second
    #define MAXN 100050
    using namespace std;
    int pre[MAXN][8];
    bool bo[MAXN][8];
    bool dp[MAXN][8];
    bool ed[MAXN][8];
    ULL hs[9][MAXN];
    ULL p[MAXN];
    int id[8][MAXN];
    char s[9][MAXN];
    int len[9];
    void makehs(int id){
        hs[id][0]=1;
        for(int i=1;i<=len[id];++i)
            hs[id][i]=hs[id][i-1]*31+s[id][i-1]-'a'+1;
    }
    ULL geths(int id,int l,int r){
        l--;
        return hs[id][r]-hs[id][l]*p[r-l];
    }
    int q[MAXN];
    int tail;
    void out(int cid,int l,int r)
    {
        for(int i=r;i>=l;--i)
            q[tail++]=id[cid][i];
    }
    int main() {
        p[0]=1;
        for(int i=1;i<MAXN;++i)p[i]=p[i-1]*31;
        int tt,n,m;
        scanf("%d",&tt);
        while(tt--)
        {
            scanf("%d%d",&n,&m);
            memset(bo,0,sizeof(bo));
            memset(dp,0,sizeof(dp));
            memset(ed,0,sizeof(ed));
            memset(pre,-1,sizeof(pre));
            int cid=1;
            for(int i=0;i<4;++i){
                scanf(" %s",s[i*2]);
                len[i*2]=len[i*2+1]=strlen(s[i*2]);
                for(int j=0;j<len[i*2];++j)
                {
                    s[i*2+1][j]=s[i*2][len[i*2]-j-1];
                    id[i*2][j]=cid;
                    id[i*2+1][len[i*2]-j-1]=cid++;
                }
                makehs(i*2);
                makehs(i*2+1);
            }
            scanf(" %s",s[8]);
            len[8]=strlen(s[8]);
            makehs(8);
            //整串转移
            for(int i=0;i<m;++i){
                for(int j=0;j<8;++j){
                    if(i+len[j]<=m){
                        ULL tmp1=geths(8,i+1,i+len[j]);
                        ULL tmp2=geths(j,1,len[j]);
                        if(tmp1!=tmp2)continue;
                        bo[i][j]=true;
                    }
                }
            }
    
            //开头
            for(int i=0;i<m;++i){
                for(int j=0;j<8;++j){
                    if(len[j]>i){
                        ULL tmp1=geths(8,1,i+1);
                        ULL tmp2=geths(j,len[j]-i,len[j]);
                        if(tmp1!=tmp2)continue;
                        dp[i][j]=true;
                    }
                }
            }
    
            //结尾
            for(int i=0;i<m;++i){
                for(int j=0;j<8;++j){
                    if(len[j]>len[8]-i){
                        ULL tmp1=geths(8,i+1,len[8]);
                        ULL tmp2=geths(j,1,len[8]-i);
                        if(tmp1!=tmp2)continue;
                        ed[i][j]=true;
                    }
                }
            }
    
            int pos=-1,posx,flag=0,fol;
            //转移
            for(int i=0;i<m;++i){
                for(int j=0;j<8;++j){
                    if(!dp[i][j])continue;
                    if(i==m-1){
                        pos=i;
                        posx=j;
                        flag=1;
                        break;
                    }
                    for(int k=0;k<8;++k){
                        if((j^k)==1)continue;
                        if(!ed[i+1][k])continue;
                        pos=i;
                        posx=j;
                        fol=k;
                        flag=1;
                        break;
                    }
                    for(int k=0;k<8;++k){
                        if((j^k)==1)continue;
                        if(!bo[i+1][k])continue;
                        dp[i+len[k]][k]=true;
                        pre[i+len[k]][k]=j;
                    }
                }
                if(flag)break;
            }
            if(flag==0)
            {
                puts("No solution!");
                continue;
            }
            tail=0;
            if(pos!=m-1){
                out(fol,0,m-pos-2);
            }
            while(posx!=-1){
                if(len[posx]>pos+1)out(posx,len[posx]-pos-1,len[posx]-1);
                else out(posx,0,len[posx]-1);
                int tmpx=posx;
                posx=pre[pos][posx];
                pos=pos-len[tmpx];
            }
            for(int i=tail-1;i>0;--i)printf("%d ",q[i]);
            printf("%d
    ",q[0]);
        }
        return 0;
    }
    /*
    1
    3 3
    abc
    abc
    abc
    abc
    baa
    
    */
  • 相关阅读:
    读书笔记 《如何阅读一本书》
    蓝桥杯 试题 历届试题 翻硬币 反转(开关问题)
    读书笔记 《如何阅读一本书》
    蓝桥杯 试题 历届试题 高僧斗法 博弈论
    读书笔记 《如何阅读一本书》
    蓝桥杯 试题 历届试题 格子刷油漆
    读书笔记 《如何阅读一本书》
    读书笔记 《如何阅读一本书》
    读书笔记 《如何阅读一本书》
    读书笔记 《如何阅读一本书》
  • 原文地址:https://www.cnblogs.com/L-Ecry/p/3961131.html
Copyright © 2011-2022 走看看