思路: 将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\n",q[0]); } return 0; } /* 1 3 3 abc abc abc abc baa */