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

*/
时间: 2024-10-25 12:34:29

ZOJ 3817Chinese Knot(The 2014 ACM-ICPC Asia Mudanjiang Regional First Round)的相关文章

2014 ACM/ICPC Asia Regional Guangzhou Online Wang Xifeng&#39;s Little Plot HDU5024

一道好枚举+模拟题目.转换思维视角 这道题是我做的,规模不大N<=100,以为正常DFS搜索,于是傻乎乎的写了起来.各种条件限制模拟过程 但仔细一分析发现对每个点进行全部八个方向的遍历100X100X100^8 .100X100个点,每个点在走的时候8中选择,TLE 于是改为另一个角度: 以符合要求的点为拐弯点,朝两个垂直的方向走,求出最远的距离.这样只要对每个点各个方向的长度知道,组合一下对应的就OK. 避免了每个点深搜. PS:搜索的时候x,y写反了,导致构图出现问题,以后用[dy][dx]

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu 5008(2014 ACM/ICPC Asia Regional Xi&#39;an Online ) Boring String Problem(后缀数组&amp;二分)

Boring String Problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 219    Accepted Submission(s): 45 Problem Description In this problem, you are given a string s and q queries. For each que

poj 5024&amp;&amp;&amp;2014 ACM/ICPC Asia Regional Guangzhou Online 1003(预处理)

http://acm.hdu.edu.cn/showproblem.php?pid=5024 分析:预处理每个点在八个方向的射线长度,再枚举八种L形状的路,取最大值. 注意题意是求一条最长路,要么一条直线,要么只有一个90角,即L型.其实直线就是L形的一个方向长度为0. 代码: #include<iostream> #include<map> #include<cstdio> #include<string> #include<cstring>

2014 ACM/ICPC Asia Regional Xi&#39;an Online

03 hdu5009 状态转移方程很好想,dp[i] = min(dp[j]+o[j~i]^2,dp[i]) ,o[j~i]表示从j到i颜色的种数. 普通的O(n*n)是会超时的,可以想到o[]最大为sqrt(n),问题是怎么快速找到从i开始往前2种颜色.三种.四种...o[]种的位置. 离散化之后,可以边走边记录某个数最后一个出现的位置,初始为-1,而所要求的位置就等于 if(last[a[i]]==-1) 该数没有出现过,num[i][1] = i,num[i][j+1] = num[i-1

HDU 5000 2014 ACM/ICPC Asia Regional Anshan Online DP

Clone Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/65536K (Java/Other) Total Submission(s) : 8   Accepted Submission(s) : 5 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description After eating food from Chernobyl,

2014 ACM/ICPC Asia Regional Xi&#39;an Online(HDU 5007 ~ HDU 5017)

题目链接 A题:(字符串查找,水题) 题意 :输入字符串,如果字符串中包含“ Apple”, “iPhone”, “iPod”, “iPad” 就输出 “MAI MAI MAI!”,如果出现 “Sony” 就输出“SONY DAFA IS GOOD!” ,大小写敏感. 思路 : 字符串查找,水题. 1 #include <string.h> 2 #include <stdio.h> 3 #include <iostream> 4 5 using namespace st

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;

HDU 5010 Get the Nut(2014 ACM/ICPC Asia Regional Xi&#39;an Online)

思路:广搜, 因为空格加上动物最多只有32个那么对这32个进行编号,就能可以用一个数字来表示状态了,因为只有 ‘P’   'S' 'M' '.' 那么就可以用4进制刚好可以用64位表示. 接下去每次就是模拟了. 注意:  ‘S’ 不是只有一个. 一个东西如果不是'P'在动的话要先判断周围有没有‘P’,有的话要先吃掉      'P'在动的时候如果一个位置周围有多个东西,都要吃掉. #include<iostream> #include<cstdio> #include<alg

hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi&#39;an Online)

Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 675    Accepted Submission(s): 237 Problem Description Trader Dogy lives in city S, which consists of n districts. There are n - 1