POJ-1743 Musical Theme 哈希

该题题意是给定一个音乐串,要求最长的主题串满足
可以找到两个这样的串,在对方的每一位添加一个数字
两个串互相不能够有重叠

有是多项式插值取模的hash的应用

代码如下:

#include <cstdlib>

#include <cstring>

#include <cstdio>

#define T 99991

#define MAXN 20000

#define MOD 3001

using namespace std;



typedef unsigned long long UInt64;



struct Node

{

    UInt64 key;

    int begin, end, next;

}e[3000000];



int N, seq[MAXN+5], diff[MAXN+5], head[MOD], idx;



UInt64 POW[(MAXN>>1)+5];



void getint(int &t)

{

    char c;

    while (c = getchar(), c < '0' || c > '9');

    t = c - '0';

    while (c = getchar(), c >= '0' && c <= '9') {

        t = t * 10 + c - '0';

    }

}



int Hash(UInt64 key, int begin, int end)

{ // 这里应用贪心思想,如果前面有一个提前完成的主题,一定取前面的主题 

    int Rkey = key % MOD, flag = 0;

    for (int i = head[Rkey]; i != -1; i = e[i].next) {

        if (key == e[i].key) {

            flag = 1;

            if (begin > e[i].end) {

                return true;

            }

        }

    }

    if (!flag) {

        ++idx;

        e[idx].key = key, e[idx].begin = begin;

        e[idx].end = end, e[idx].next = head[Rkey];

        head[Rkey] = idx;

    }

    return false;

} 



bool Accept(int k)

{

    UInt64 key = 0;

    idx = -1;

    memset(head, 0xff, sizeof (head));

    for (int i = 1; i <= k; ++i) {

        key = key * T + diff[i];

    }

    if (Hash(key, 0, k)) {

        return true;

    }

    for (int i = 2; i <= N-k+1; ++i) {

        key -= diff[i-1] * POW[k-1];

        key = key * T + diff[i+k-1];

        if (Hash(key, i-1, i+k-1)) {

            // 这里的begin和end要映射到原数组中

            return true;

        }

    }

    return false;

}



int bsearch(int l, int r)

{

    int mid;

    while (l <= r) {

        mid = (l+r) >> 1;

        if (Accept(mid)) {

            l = mid + 1;

        }

        else {

            r = mid - 1;

        }

    } 

    return r;

}



int main()

{

    POW[0] = 1;

    int ans; 

    for (int i = 1; i <= 10000; ++i) {

        POW[i] = POW[i-1] * T;

    }

    while (scanf("%d", &N), N) {

        for (int i = 0; i < N; ++i) {

            getint(seq[i]);

        //    scanf("%d", &seq[i]);

        }

        N -= 1;

        for (int i = 1; i <= N; ++i) {

            diff[i] = seq[i] - seq[i-1] + 203;

        }

        if (N >= 9) {

            ans = bsearch(4, N>>1);

            if (ans >= 4) {

                printf("%d\n", ans+1);

            }

            else {

                puts("0");

            }

        }

        else {

            puts("0");

        }

    }

    return 0;    

} 

 

 

你可能感兴趣的:(theme)