zoj 3817 Chinese Knot(hash+暴力)

题目链接:zoj 3817 Chinese Knot

题目大意:给出四个字符串,对应着同心结的四条边,现在给定一个目标串,可以从任意节点开始移动,问是否可以匹配目标串。

解题思路:用hash将四个字符串的正序和逆序处理出来,然后dfs枚举,每次保留起始位置和移动方向即可。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;

#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)

const int maxn = 100005;
const ull X = 107;

char str[maxn];
int N, M;
vector<pii> ans;
ull G[12][maxn], H[maxn], T[maxn];

void init () {
    scanf("%d%d", &N, &M);
    for (int i = 0; i < 4; i++) {
        scanf("%s", str+1);

        G[lson(i)][N+1] = G[rson(i)][N+1] = 0;
        for (int j = N; j >= 1; j--) {
            G[lson(i)][j] = G[lson(i)][j+1] * X + (str[j] - ‘a‘);
            G[rson(i)][j] = G[rson(i)][j+1] * X + (str[N-j+1] - ‘a‘);
        }
    }

    scanf("%s", str+1);
    H[M+1] = 0;
    for (int j = M; j >= 1; j--)
        H[j] = H[j+1] * X + (str[j] - ‘a‘);
}

bool dfs (int k, int pos, int dir, int L) {
    if (L == 0)
        return true;

    int len = min(N - pos + 1, L);
    if (G[(k<<1)|dir][pos] - G[(k<<1)|dir][pos+len] * T[len] == H[M-L+1] - H[M-L+len+1] * T[len]) {
        ans.push_back(make_pair(k * N + (dir ? N + 1 - pos : pos), dir));
        L -= len;

        if (L == 0)
            return true;

        for (int i = 0; i < 4; i++) {
            for (int d = 0; d < 2; d++) {
                if (k == i && (d^1) == dir)
                    continue;

                if (dfs(i, 1, d, L))
                    return true;
            }
        }

        ans.pop_back();
    }

    return false;
}

bool solve () {
    for (int i = 0; i < 4; i++) {
        for (int pos = 1; pos <= N; pos++) {
            for (int d = 0; d < 2; d++) {
                ans.clear();
                if (dfs(i, pos, d, M))
                    return true;
            }
        }
    }
    return false;
}

int main () {
    int cas;
    scanf("%d", &cas);

    T[0] = 1;
    for (int i = 1; i < maxn; i++)
        T[i] = T[i-1] * X;

    while (cas--) {
        init();
        if (solve()) {

            int p = 0;
            for (int k = 0; k < ans.size(); k++) {
                int u = (ans[k].first - 1) / N + 1, dir = ans[k].second;

                if (dir == 0) {
                    for (int i = ans[k].first; i <= u * N && p < M; i++, p++) {
                        if (p) printf(" ");
                        printf("%d", i);
                    }
                } else {
                    for (int i = ans[k].first; i > (u-1) * N && p < M; i--, p++) {
                        if (p) printf(" ");
                        printf("%d", i);
                    }
                }
            }
            printf("\n");
        } else
            printf("No solution!\n");
    }
    return 0;
}
时间: 2024-09-29 17:20:37

zoj 3817 Chinese Knot(hash+暴力)的相关文章

ZOJ 3817 Chinese Knot(牡丹江网络赛I题)

ZOJ 3817 Chinese Knot 题目链接 思路:万万没想到这题直接hash+暴力剪枝就可以了,把4个串正逆都hash出来,然后每次枚举起点去dfs记录下路径即可,剪枝为如果一旦有一点不匹配就不往后搜(这个很容易想到0 0) 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; typedef unsi

ZOJ 3817 Chinese Knot

题意:给定4个长度为N的字符串( N <= 100000),然后构成一个“中国结”,给定目标串,问能否从某个节点出发走一遍得到目标串,其中不能连续通过3个中心节点,也就是从字符串一个端点转移到其他端点后必须沿着这条字符串走. 分析:对4个字符串正反两面和目标串建立相应hash函数,然后暴力枚举每一个位置出发就可以了,可以有正反两个方向的走法.中间注意一下细节差不多就可以了. 代码: 1 #include <bits/stdc++.h> 2 #pragma comment(linker,

zoj 2313 Chinese Girls&#39; Amusement 解题报告

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313 题目意思:有 N 个人(编号依次为1~N)围成一个圆圈,要求求出最大的 K (1 ≤ K ≤ N/2),表示从编号为1的人开始,将球传递给他后一个人数起的第K个人,第K个人又传递给往后数的第K个人......要求这样传递下去,且每个人都有机会接到球.也就是不存在当未使得全部人都接到一次球的情况下,某个人接收到两次以上的球. 详细的解题报告在这里: http:/

hdu 4886 TIANKENG’s restaurant(2)(hash+暴力)

题目链接:hdu 4886 TIANKENG's restaurant(2) 题目大意:给定一个字符串S,要求在该字符串中找到一个最短并且字符串字典序最小. 解题思路:每次枚举字符串的长度,然后将S中所有该长度的子串映射成一个9进制数,最后再遍历一遍标记数组. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1000005; i

垃圾佬的旅游III(Hash + 暴力)

题目链接:http://120.78.128.11/Problem.jsp?pid=3445 最开始的思路就是直接暴力求解,先把所有的数值两两存入结构体,再从小到大枚举.用二分的思路去判断数值以及出现,结果TLE,但优化一下应该也能过,因为题目说只有两组数据.代码如下: 1 #include <iostream> 2 #include <string> 3 #include <cstdio> 4 #include <cstdlib> 5 #include &

zoj 3818 Pretty Poem(暴力处理字符串)2014年牡丹江赛区网络赛

Pretty Poem Time Limit: 2 Seconds      Memory Limit: 65536 KB Poetry is a form of literature that uses aesthetic and rhythmic qualities of language. There are many famous poets in the contemporary era. It is said that a few ACM-ICPC contestants can e

ZOJ (狗狗)1426 Counting Rectangles(暴力)

Counting Rectangles Time Limit: 2 Seconds      Memory Limit: 65536 KB We are given a figure consisting of only horizontal and vertical line segments. Our goal is to count the number of all different rectangles formed by these segments. As an example,

zoj 2976 Light Bulbs(暴力枚举)

Light Bulbs Time Limit: 2 Seconds      Memory Limit: 65536 KB Wildleopard had fallen in love with his girlfriend for 20 years. He wanted to end the long match for their love and get married this year. He bought a new house for his family and hired a

zoj 3817 2014牡丹江网赛 字符串哈希

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5349 比赛的时候没看这道题,遗憾,不过想到算法不难,但是写代码比较考代码能力,我自己写了两次都不行,还是看了别人代码,写下了这个 学到: 1.hash字符串第一个下表为0的空起来,写起来方便 2.hash匹配的全部情况就是以text串的所有位置为起点做匹配,当text比patern小而且text可以循环时,这么确定 3.dfs的时候,为了加快,可以预估计至少需要匹配多长 in