BZOJ 3916 Baltic 2014 friends Hash

题目大意

给出一个字符串,这个字符串是由两个相同的字符串连接之后再加一个字母的到的,求原串。

思路

枚举加的字母是哪一个,之后分情况讨论,根据hash值来判定是否符合题目要求。注意判重。

CODE

#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 2000010
#define BASE 23333
using namespace std;

int length, mid;
char s[MAX];

unsigned long long _hash[MAX];
unsigned long long power[MAX];

int cnt;
char ans[MAX], now[MAX];
unsigned long long h_ans, h_now;

inline unsigned long long GetHash(int l, int r)
{
    return _hash[r] - _hash[l - 1] * power[r - l + 1];
}

inline bool Judge(int dismiss)
{
    static unsigned long long front, tail;
    if(dismiss < mid) {
        front = GetHash(1, dismiss - 1) * power[mid - dismiss] + GetHash(dismiss + 1, mid);
        tail = GetHash(mid + 1, length);
    }
    else if(dismiss == mid) {
        front = GetHash(1, mid - 1);
        tail = GetHash(mid + 1, length);
    }
    else {
        front = GetHash(1, mid - 1);
        tail = GetHash(mid, dismiss - 1) * power[length - dismiss] + GetHash(dismiss + 1, length);
    }
    if(front == tail) {
        if(h_ans == front)  return false;
        h_ans = front;
        int top = 0;
        if(dismiss <= mid)
            for(int i = mid + 1; i <= length; ++i)
                ans[++top] = s[i];
        else
            for(int i = 1; i < mid; ++i)
                ans[i] = s[i];
        return true;
    }
    return false;
}

int main()
{
    cin >> length;
    if(!(length&1)) {
        puts("NOT POSSIBLE");
        return 0;
    }
    mid = (length >> 1) + 1;
    scanf("%s", s + 1);
    power[0] = 1;
    for(int i = 1; i <= length; ++i)
        power[i] = power[i - 1] * BASE;
    for(int i = 1; i <= length; ++i)
        _hash[i] = _hash[i - 1] * BASE + s[i];
    for(int i = 1; i <= length; ++i) {
        cnt += Judge(i);
        if(cnt > 1) break;
    }
    if(!cnt)
        puts("NOT POSSIBLE");
    if(cnt == 1)
        puts(ans + 1);
    if(cnt > 1)
        puts("NOT UNIQUE");
    return 0;
}
时间: 2024-10-09 23:28:19

BZOJ 3916 Baltic 2014 friends Hash的相关文章

BZOJ 2761 不重复数字 (Hash)

题解:直接使用STL中的hash去重即可 #include <cstdio> #include <map> using namespace std; int ans[50010]; int main(){ int T,n,tmp; scanf("%d",&T); while(T--){ int cnt=0; map<int,int>m; scanf("%d",&n); for(int i=0;i<n;i++)

BZOJ 3916: [Baltic2014]friends( hash )

字符串哈希..然后枚举每一位+各种判断就行了 -------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int MOD = 1000000007; const i

BZOJ 3574 HNOI 2014 抄卡组 字符串Hash+STL

题目大意:给出一些表示卡组的字符串,字符串中可能出现'*'符号(并不是BZ上以前写的'#'号,更不是" '*' "...),这个符号可以代表任意字符串(包括空串).问所有的字符串是否能够相同. 思路:题目描述,样例有误,数据范围坑爹,官方数据出错,BZ输入流过大RE..这题做完了都不知道该说什么好了... 整个就是一个常数很大的O(n)模拟题而已... 首先数据范围十分坑爹,N*最长字符串长度<=2*10^8,你这让我怎么开数组?好吧,那就全篇vector 先弄出所有字符串的Ha

BZOJ 3555 CTSC 2014 企鹅QQ Hash

题目大意:为了分辨那些qq是一个人的小号,我们需要写一套程序来判定哪些名称是相似的.相似的定义是有且只有一个位置的字符不同. 思路:数据范围不算太大,很明显的Hash,二分都不用.听老师说今年去CTSC考试的学长中有一个人没AC这个题是因为想多了.他当时写了Hash,然后闲的没事自己出一组数据卡掉了自己的hash,然后就不敢交hash了,最后交了一个Trie树,结果T了..血的教训告诉我们,不要想太多.. 先预处理每个字符串,得到hash值.然后枚举每一位,在O(1)的时间中吧这一位去掉的Has

BZOJ 1090 字符串折叠(Hash + DP)

题目链接 字符串折叠 区间DP.f[l][r]为字符串在区间l到r的最小值 正常情况下 f[l][r] = min(f[l][r], f[l][l + k - 1] + f[l + k][r]); 当l到r以k为周期时 f[l][r] = min(f[l][r], 2 + sz(k) + f[l][l + (r - l + 1) / k - 1]); 判重的时候为了方便我用了哈希……当然其他方法应该也是可以的~ #include <bits/stdc++.h> using namespace

bzoj 3197 [Sdoi2013]assassin(Hash+DP+KM)

Description Input Output Sample Input 4 1 2 2 3 3 4 0 0 1 1 1 0 0 0 Sample Output 1 HINT [思路] Hash,DP,KM 树的形态可以有多种但是他的中心只有一个.先找出中心,如果在边上则新建一个节点.以中心为根建树,同时求出Hash.Hash函数如下: H[u]=((((A*H[son1])*p+H[son2])*p+H[son3])*p) 通过判断hash值和节点深度dep就可直到是否同构. 在树上进行DP

BZOJ 3555: [Ctsc2014]企鹅QQ hash

3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=3555 Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大的互联网功能体验,满足用户对社交.资讯.娱乐.交易等多方面的需

BZOJ 2151 种树 贪心+优先队列+HASH

题意:链接 方法:贪心+优先队列 解析: 首先裸上贪最大的肯定不对. DP可行么?可行,两个数组一个记录选一个记录不选好像差不多n^2? 不过还是想想贪心. 贪最大的为什么不对? 因为有可能它旁边的两个加起来比它更优越? 所以能否找到一点关系呢? 既然话都说到这了,两个加起来可能更优越. 所以我们在选了最大的之后是否应该回推一个值呢?代表选旁边俩. 我们发现选旁边俩是两个单位,选一个是一个单位,如果我们推回去某个值后这个值相当于对应删去一个单位选两个单位,即增加一个单位,这显然不会影响最终我们选

[BZOJ 3669][NOI 2014]魔法森林(Link-Cut Tree)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3669 记得四个月之前的NOI同步赛,我还只会玩脚丫子.... 记得我当时看到这个题整个人就吓傻了,完全不知道怎么做,然后NOI同步赛就这样爆零了... 如今我学了LCT这个神器,再看这个题,感觉不再那么难了. 其实这个题的标准解法是SPFA,改得完全认不出来的SPFA. orz太神了,完全没见识过这么神犇的SPFA,NOIP 2014考了SPFA,NOI 2014也考了SPFA,