2020年字符串专题训练赛02

H:restoring the expression
考察知识点:字符串hash
题目大意:一个串是否能将他分割成a+b=c的形式(首位不能是0,个位数字不算)
方法一:暴力枚举,分情况讨论,事实证明是可行的,但是由于分类过于复杂,很难统一完成,因此,不推荐
方法二:hash //当我看其他人的博客讲说hash时,黑人问号脸。
不得不在这感叹hash的作用真的大
需要了解hash的几个公式
. Hash[i] = (Hash[i-1] *base+ s[i]) % MOD
2. [l , r]子串的Hash值,Hash[r] - Hash[l - 1] * p[r-i+1]
3. p[r-i+1]=base的r-i+1次方
代码:这里我的base选择的是10,mod数选的1e9+7
(怕ull卡掉)

在这里#include <algorithm>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+5;
const ll MOD = 1e9+7;
ll Hash[maxn],pw[maxn],base = 10;
int len;

char str[maxn];
ll get_hash(int l,int r){
    ll ret = (Hash[r]-Hash[l-1]*pw[r-l+1])%MOD;
    if(ret<0) ret+=MOD;                        
    return ret;
}
void has(int a,int b)
{
    rep(i,1,a+1) printf("%c",str[i]);
    printf("+");
    rep(i,a+1,a+b+1) printf("%c",str[i]);
    printf("=");
    rep(i,a+b+1,len+1) printf("%c",str[i]);
}
bool check(int lena,int lenb){
    if(lena<=0||lenb<=0) return 0;
    ll c = get_hash(lena+lenb+1,len);
    ll a = get_hash(1,lena) , b = gethash(lena+1,lena+lenb);
    if(lenb!=1&&str[lena+1]=='0') return 0;    
    if((a+b)%MOD==c){
    has(lena,lenb);
    return 1;
    }
    return 0;
}

int main()
{
    scanf("%s",str+1);
    len = strlen(str+1);
    pw[0] = 1;
    rep(i,1,len+1) pw[i] = (pw[i-1]*base)%MOD;
    Hash[0] = 0;
    for(int i=0;i<len+1;i++)
    
     Hash[i] = (Hash[i-1]*base+(str[i]-'0'))%MOD;
   for(int i=len/2;i<=len+2;i++)
        if(str[i]=='0'&&i!=len) 
		continue;       
        int len1 = len-i+1;
        if(check(len1,len-2*len1))
		 break;
        if(check(len1-1,len-2*len1+1))
		 break;
        if(check(len-2*len1,len1))
		 break;
        if(check(len-2*len1+1,len1-1))
		 break;
    }
}
插入代码片

你可能感兴趣的:(acm)