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 <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
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;
}
}
插入代码片