HDU 4749: Parade Show

看大神代码,发现上交大神很棒的一个思路

题意:

在源数字串中找出尽量多的连续子串,要求子串任意两值的大小关系与目标串相同位置的值的大小关系相同。求源串能拿出的子串的最大数量。

关键词:

RK-Hash

优点:

O(k)时间完成匹配检查(关键在于他能O(1) 完成 所有 相同位 检查)

方法:

对于一个K值,用某个进制数来表示其位置。

        比如 123121 中 的值 1 最后表示成 100101。

        然后,对于目标串也RK-hash,对于某个值,只要比较这个数,就能知道是否相同位都相同了。

代码留恋:

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 100005, K = 26;
int a[N], b[N], n, m, k;
unsigned long long phs[K], ahs[K], DEF;

const unsigned long long base = 29;

int main() {
    while (scanf("%d%d%d", &n, &m, &k) == 3) {
        for (int i = 0; i < n; ++i) {
            scanf("%d", a + i);
        }
        for (int i = 0; i < m; ++i) {
            scanf("%d", b + i);
        }
        DEF = 1;
        for (int i = 0; i < m - 1; ++i) {
            DEF *= base;
        }
        memset(phs, 0, sizeof(phs));
        memset(ahs, 0, sizeof(ahs));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < k; ++j) {
                phs[j] *= base;
            }
            phs[b[i] - 1] += 1; 
        } 
        vector<int> v;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < k; ++j) {
                ahs[j] *= base;
            }
            ahs[a[i] - 1] += 1;
            if (i >= m - 1) {
                int t1 = k - 1, t2 = k - 1;  
                bool sue = false;
                while (true) {
                    while (t1 >= 0 && ahs[t1] == 0) {
                        --t1;
                    }
                    while (t2 >= 0 && phs[t2] == 0) {
                        --t2;
                    }
                    if (t1 == -1 && t2 == -1) {
                        sue = true;
                        break;
                    }
                    if (t1 == -1 || t2 == -1) {
                        break;
                    }
                    if (ahs[t1] != phs[t2]) {
                        break;
                    }
                    --t1, --t2;
                }
                if (sue) {
                    v.push_back(i - m + 1);
                }
                ahs[a[i - m + 1] - 1] -= DEF;
            }
        }
        int last = -m - 5, ans = 0;
        for (int i = 0; i < (int)v.size(); ++i) {
            if (v[i] < last + m) {
                continue;
            } else {
                last = v[i];
                ++ans;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

       

 

posted on 2013-09-21 23:10  ShineCheng  阅读(416)  评论(0编辑  收藏  举报

导航