• POJ 1743 Musical Theme Hash+二分法


    标题效果:有一个美丽的旋律,它们是由一些不大于88音调。如果计为五个音调的量度,问:是否有相同的节奏的多个部分(相同的差,以及两者之间的相同的节奏不能重叠),并寻求最长长度。


    思考:这个问题是八人中的问题,正解是自己主动机后缀,但我不会。

    但是某神犇说过:“Hash大法好”。

    于是这个题Hash+二分也能够解决。分析时间复杂度。2w个点,二分logn。hash挂链推断O(kn),总复杂度O(knlogn)。解决。
    将原数组两两做差,然后依照这个数组hash。

    二分枚举最长的同样的韵律长度。枚举每个開始的时间,然后推断两个韵律是否重叠,这个都放在hash表里即可了。


    CODE:


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define BASE 177
    #define MAX 20010
    using namespace std;
    
    struct HashSet{
    	static const int mo = 9997;
    	int head[mo + 100],total;
    	int next[MAX],pos[MAX];
    	unsigned long long true_hash[MAX];
    	
    	void Clear() {
    		memset(head,0,sizeof(head));
    		total = 0;
    	}
    	bool Insert(unsigned long long hash,int _pos,int ans) {
    		int x = hash % mo;
    		for(int i = head[x];i;i = next[i])
    			if(true_hash[i] == hash && _pos - pos[i] > ans)
    				return true;
    		next[++total] = head[x];
    		true_hash[total] = hash;
    		pos[total] = _pos;
    		head[x] = total;
    		return false;
    	}
    }map;
    
    unsigned long long p[MAX];
    unsigned long long hash[MAX];
    int cnt;
    int _src[MAX],src[MAX];
    
    void Pretreatment();
    inline bool Judge(int ans);
    
    int main()
    {
    	Pretreatment();
    	while(scanf("%d",&cnt),cnt) {
    		for(int i = 1;i <= cnt; ++i)
    			scanf("%d",&_src[i]);
    		for(int i = 1;i < cnt; ++i)
    			src[i] = _src[i + 1] - _src[i] + 88;
    		hash[0] = 0;
    		for(int i = 1;i < cnt; ++i)
    			hash[i] = hash[i - 1] * BASE + src[i];
    		int l = 0,r = cnt,ans = 0;
    		while(l <= r) {
    			int mid = (l + r) >> 1;
    			if(Judge(mid))
    				l = mid + 1,ans = mid;
    			else	r = mid - 1;
    		}
    		ans++;
    		if(ans < 5)	ans = 0;
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    void Pretreatment()
    {
    	p[0] = 1;
    	for(int i = 1;i < MAX; ++i)
    		p[i] = p[i - 1] * BASE;
    }
    
    inline bool Judge(int ans)
    {
    	map.Clear();
    	for(int i = ans;i < cnt; ++i)
    		if(map.Insert((unsigned long long)hash[i] - hash[i - ans] * p[ans],i,ans))
    			return true;
    	return false;
    }


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    258. Add Digits 数位相加到只剩一位数
    7. Reverse Integer 反转整数
    9. Palindrome Number 回文数的判断
    824. Goat Latin山羊拉丁文
    819. Most Common Word 统计高频词(暂未被禁止)
    Angular 2 模板语法
    HTML DOM Style opacity 属性
    Basic concepts (C language) – C 中文开发手册
    JavaScript手册 | JS Array 对象中的fill()方法
    HTML <form> 标签
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4802529.html
Copyright © 2020-2023  润新知