Codeforces 898F 字符串hash

F. Restoring the Expression

题意:给出一个字符串,要把它折分成三部分 a、b、c , 使得 a+b=c 。输出任何一种可行情况。

tags:字符串 hash

因为 a+b=c ,所以 lena、lenb 至少要有一个等于 lenc 或 lenc-1  。所以枚举 lenc,每次检验一下可不可行。

但每次都暴力检验肯定超时,这里把字符串hash 一下,根据 hash值 快速检验。

记一下模板:

const int mod = 1e9+7;
ll  Hash[N], p[N], Base=10;
void Init(string si)
{
    int len = si.size();
    Hash[0]=0;
    for(int i=0; i<len; ++i)
        Hash[i+1] = (Hash[i]*Base%mod+si[i]-‘0‘)%mod;
    p[0]=1;
    for(int i=0; i<len; ++i)
        p[i+1] = p[i]*Base%mod;
}
ll  get(int l, int r)
{
    if(r<0 || l-1<0 || r-l+1<0) return 0;
    return (Hash[r]-Hash[l-1]*p[r-l+1]%mod+mod)%mod;
}

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 1000005;

const int mod = 1e9+7;
ll  Hash[N], p[N], Base=10;
void Init(string si)
{
    int len = si.size();
    Hash[0]=0;
    for(int i=0; i<len; ++i)
        Hash[i+1] = (Hash[i]*Base%mod+si[i]-‘0‘)%mod;
    p[0]=1;
    for(int i=0; i<len; ++i)
        p[i+1] = p[i]*Base%mod;
}
ll  get(int l, int r)
{
    if(r<0 || l-1<0 || r-l+1<0) return 0;
    return (Hash[r]-Hash[l-1]*p[r-l+1]%mod+mod)%mod;
}

string si;
int len, lenc;
void print(int lena, int lenb)
{
    rep(i,0,lena-1) putchar(si[i]);  putchar(‘+‘);
    rep(i,lena,lena+lenb-1) putchar(si[i]); putchar(‘=‘);
    rep(i,lena+lenb,len-1) putchar(si[i]);
}

bool check(int lena, int lenb)
{
    string s1=si.substr(0,lena);
    string s2=si.substr(lena,lenb);
    string s3=si.substr(lena+lenb,len-lena-lenb);
    int flag=0, len3=len-lena-lenb, i, j;
    for(i=lena-1, j=lenb-1; i>=0 && j>=0; --i, --j)
    {
        int a1=s1[i]-‘0‘, a2=s2[j]-‘0‘, a3=a1+a2+flag;
        if(a3>=10) a3-=10, flag=1;
        else flag=0;
        if(a3!=s3[len3-(lena-i)]-‘0‘) return false;
    }
    return true;
}
bool solve(int lena, int lenb)
{
    if(lena>lenc || lenb>lenc) return false;
    if(lena<0 || lenb<0) return false;
    if(si[lena]==‘0‘ && lenb!=1) return false;
    if(si[lena+lenb]==‘0‘ && len-lena-lenb!=1) return false;
    if( (get(1,lena)+get(lena+1, lena+lenb))%mod != get(lena+lenb+1, len) ) return false;
    //return true;
    return  check(lena, lenb);
}
int main()
{
    cin>>si;
    Init(si);
    len=si.size();
    for(lenc=1; lenc<=len-2; ++lenc)
    {
        if(solve(lenc, len-lenc*2)) {
            print(lenc, len-lenc*2); return 0;
        }
        if(solve(lenc-1, len-lenc-(lenc-1))) {
            print(lenc-1, len-lenc-(lenc-1)); return 0;
        }
        if(solve(len-lenc*2, lenc)) {
            print(len-lenc*2, lenc); return 0;
        }
        if(solve(len-lenc-(lenc-1), lenc-1)) {
            print(len-lenc-(lenc-1), lenc-1); return 0;
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/sbfhy/p/8433653.html

时间: 2024-08-23 07:29:14

Codeforces 898F 字符串hash的相关文章

codeforces gym 101164 K Cutting 字符串hash

题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #

hdu 1880 魔咒词典(字符串hash)

题目链接:hdu 1880 魔咒词典 题意: 给你一个10w的词典,让你输出对应的字段. 题解: map暴力存字符串肯定会卡内存,这里用BKDR字符串hash一下,用map映射一下. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef unsigned long long ull; 5 6 const int N=1e5+7,seed=133

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

hdu4821 String 字符串hash(bkdrhash)

题意:给定m,l,一个字符串str. 我们定义一个子串为"recoverable"串 当 1.长度为 M*L 2.把这个好串分成M段,每段长度为L,且每段各不相同. 求"recoverable"串的个数,串相同位置不同也算不同. 思路:预处理数组hash,hash[i]表示从i位置到尾的字符串hash值.这里数组为unsigned long long型,因为可以自动取模.然后枚举 前l个位置,每次向后翻滚(将前一个长度为l的段hash值从map中去除,将翻滚后新出现

字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍. 这题的思路是这样的: 1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界:不存在就缩小上界): 2)主要是对答案的判断(judge函数

uva 10391 Compound Words (字符串-hash)

Problem E: Compound Words You are to find all the two-word compound words in a dictionary. A two-word compound word is a word in the dictionary that is theconcatenation of exactly two other words in the dictionary. Input Standard input consists of a

[知识点] 字符串Hash

1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简单的表达,更方便的用于判重.在搜索的时候,或是动规的时候,都有过类似的做法.在实际应用中,也是非常重要的,这也就是为什么存在什么暴雪公司的Hash算法等等:加密环节也是Hash的重要之处,MD5码就是一个经典的例子. 字符串Hash的方式多式多样,重点来解释一下最简单的,最常用的. 3.BKDRHa

线段树 + 字符串Hash - 580E Kefa and Watch

Kefa and Watch Problem's Link Mean: 给你一个长度为n的字符串s,有两种操作: 1 L R C : 把s[l,r]全部变为c; 2 L R d : 询问s[l,r]是否是周期为d的重复串. analyse: n最大为1e5,且m+k最大也为1e5,这就要求操作1和操作2都要采用logn的算法,所以用线段树. 对于更新操作,使用区间更新就可解决. 主要是如何在logn的时间内完成询问操作. 我们采用线段树维护hash值的方法. 结合于类似KMP的性质,我们发现,字

bnu36907 Subpalindromes 字符串hash+线段树

bnu36907 Subpalindromes 字符串hash+线段树 题意:给一个字符串(<=1e5), 进行操作和查询(<=1e5). 1)将指定位置的字符改为c 2)询问l-r的子串,是否是回文串. 解法 :区间维护pl和pr,表示从左到右的hash和从右到左的hash,然后在up和query中合并区间,最后判断pl和pr是否相等即可. #include <cstdio> #include <ctime> #include <cstdlib> #inc