ACM-ICPC 2018 南京赛区网络预赛 I Skr (马拉车+hash去重)或(回文树)
https://nanti.jisuanke.com/t/30998
题意
给一串由0..9组成的数字字符串,求所有不同回文串的权值和。比如说“1121”这个串中有“1”,“2”,“11”,“121”三种回文串,他们的权值分别是1,2,11,121。最终输出ans=135。
分析
第一次知道马拉车是manacher。。。涨姿势了
在马拉车进行的过程中,进行子回文串的统计去重。
这里的哈希去重方法重点学习理解。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <ctime> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; #define ms(a, b) memset(a, b, sizeof(a)) #define pb push_back #define mp make_pair #define pii pair<int, int> //#define eps 0.0000000001 #define IOS ios::sync_with_stdio(0);cin.tie(0); #define random(a, b) rand()*rand()%(b-a+1)+a #define pi acos(-1) //const ll INF = 0x3f3f3f3f3f3f3f3fll; const int inf = 0x3f3f3f3f; const int maxn = 2e6 + 10; const int maxm = 3000000 +10; const int mod = 1000000007;ull base=10007; ull p[maxn<<1],has[maxn<<1]; ll pw[maxn<<1],sum[maxn<<1]; const int MOD=400007; int head[maxn<<1],nxt[maxn<<1],cnt=0; ull val[maxn]; bool exist(ull now){int u=now%MOD;for(int i=head[u];i;i=nxt[i]){if(val[i]==now) return true;}val[cnt]=now;nxt[cnt]=head[u];head[u]=cnt++;return false; } ull gethas(int l,int r){return has[r]-has[l-1]*p[r-l+1]; } ll solve(int l,int r){ull tmp=gethas(l,r);if(exist(tmp)) return 0;ll ans=(sum[r]-sum[l-1]*pw[(r-l+1+1)/2]%mod+mod)%mod;return ans; } char s[maxn]; char Ma[maxn<<1]; int Mp[maxn<<1]; ll Manacher(char s[],int len){int l=0;Ma[l++]='$';Ma[l++]='#';for(int i=0;i<len;i++){Ma[l++]=s[i];Ma[l++]='#';}Ma[l]=0;pw[0]=p[0]=1;has[0]=sum[0]=0;for(int i=1;i<=l;i++){p[i]=p[i-1]*base;has[i]=has[i-1]*base+Ma[i];pw[i]=pw[i-1]*10%mod;if(Ma[i]>='0'&&Ma[i]<='9'){sum[i]=(sum[i-1]*10+Ma[i]-'0')%mod;}else{sum[i]=sum[i-1];}}ll ans=0;int mx=0,id=0;for(int i=0;i<l;i++){if(Ma[i]!='#') ans=(ans+solve(i,i))%mod;Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;while(Ma[i+Mp[i]]==Ma[i-Mp[i]]){if(Ma[i+Mp[i]]!='#') ans=(ans+solve(i-Mp[i],i+Mp[i]))%mod;Mp[i]++;}if(mx<i+Mp[i]){mx=i+Mp[i];id=i;}}return ans; } int main() { #ifdef LOCALfreopen("in.txt", "r", stdin); // freopen("input.txt", "w", stdout); #endifscanf("%s",s);int len=strlen(s);printf("%lld\n",Manacher(s,len));return 0; }
回文树的做法是先构建一颗回文树,然后dfs奇偶节点,当前节点的所代表的数字=当前添加的数字*pow(10,当前回文串长度-1) +他父亲的数字*10+当前添加的数字。
比如:33->1331 就是1*1000+33+1。此外有点卡空间,注意内存使用
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <ctime> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; #define ms(a, b) memset(a, b, sizeof(a)) #define pb push_back #define mp make_pair #define pii pair<int, int> //#define eps 0.0000000001 #define IOS ios::sync_with_stdio(0);cin.tie(0); #define random(a, b) rand()*rand()%(b-a+1)+a #define pi acos(-1) //const ll INF = 0x3f3f3f3f3f3f3f3fll; const int inf = 0x3f3f3f3f; const int maxn = 2e6 + 10; const int maxm = 3000000 +10; const int mod = 1e9+7;struct PAM{int nxt[maxn][10];int fail[maxn];int cnt[maxn];int num[maxn];int len[maxn];int s[maxn];int last,n,p;int newnode(int w){for(int i=0;i<26;i++) nxt[p][i]=0;num[p]=cnt[p]=0;len[p]=w;return p++;}void init(){n=last=p=0;newnode(0);newnode(-1);s[n]=-1;fail[0]=1;}int get_fail(int x){while(s[n-len[x]-1]!=s[n]) x=fail[x];return x;}void add(int c){c-='0';s[++n]=c;int cur=get_fail(last);if(!nxt[cur][c]){int now=newnode(len[cur]+2);fail[now]=nxt[get_fail(fail[cur])][c];nxt[cur][c]=now;num[now]=num[fail[now]]+1;}last=nxt[cur][c];cnt[last]++;}void Count(){for(int i=p-1;i>=0;i--) cnt[fail[i]]+=cnt[i];} }; PAM pam; char s[maxn]; ll odd=0; ll even=0; ll qpow(ll a,ll b){ll res=1;while(b){if(b&1) res=a*res%mod;b>>=1;a=a*a%mod;}return res; } void dfs_odd(int x,ll fa){for(int i=1;i<=9;i++){if(pam.nxt[x][i]){ll cur;if(pam.len[pam.nxt[x][i]]==1){odd=(i+odd)%mod;cur=i;}else{cur=(i*qpow(10,pam.len[pam.nxt[x][i]]-1)%mod+i+fa*10%mod)%mod;odd=(odd+cur%mod)%mod;}dfs_odd(pam.nxt[x][i],cur);}} } void dfs_even(int x,ll fa){for(int i=1;i<=9;i++){if(pam.nxt[x][i]){ll cur=(i*qpow(10,pam.len[pam.nxt[x][i]]-1)%mod+i+fa*10%mod)%mod;even=(even+cur)%mod;dfs_even(pam.nxt[x][i],cur);}} } int main() { #ifdef LOCALfreopen("in.txt", "r", stdin); // freopen("input.txt", "w", stdout); #endifpam.init();scanf("%s",s);int len=strlen(s);for(int i=0;i<len;i++) pam.add(s[i]);dfs_odd(1,0);dfs_even(0,0);printf("%lld\n",(odd+even)%mod);return 0; }
转载于:https://www.cnblogs.com/fht-litost/p/9593930.html
ACM-ICPC 2018 南京赛区网络预赛 I Skr (马拉车+hash去重)或(回文树)相关推荐
- ACM-ICPC 2018 南京赛区网络预赛 I. Skr (马拉车+字符串hash/回文自动机)
题目链接 题意: 给你一个只有0~9的数字组成的字符串,定义一个字符串的价值就是他表示的数字,"120"的价值是120 问你在字符串内不同的回文子串的价值总和是多少 解析: 马拉车 ...
- ACM-ICPC 2018 南京赛区网络预赛 I.Skr(Manacher马拉车+Hash哈希/回文树)
题目 给一个只由数字构成的字符串s(|s|<=2e6) 求s的所有本质不同字符串之和%1e9+7, 每一个不同字符串的贡献为其十进制下的值 思路来源 https://blog.csdn.net/ ...
- ACM-ICPC 2018 南京赛区网络预赛
轻轻松松也能拿到区域赛名额,CCPC真的好难 An Olympian Math Problem 问答 只看题面 54.76% 1000ms 65536K Alice, a student of gra ...
- ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps 线段树
目录 ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps 线段树 题面 题意 思路 ACM-ICPC 2018 南京赛区网络预赛 Lpl and En ...
- ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall
题目链接:https://nanti.jisuanke.com/t/30991 2000ms 262144K Feeling hungry, a cute hamster decides to ord ...
- ACM-ICPC 2018 南京赛区网络预赛 AC Challenge
Dlsj is competing in a contest with n (0 < n \le 20)n(0<n≤20) problems. And he knows the answe ...
- ACM-ICPC 2018 南京赛区网络预赛 - AC Challenge(状压DP)
ACM-ICPC 2018 南京赛区网络预赛 - AC Challenge 题意: 有n个题目,每个题目有一些信息,,第 t 个过第 i 题会得到分数 t*ai + bi 在过第 i 题前必须要先过 ...
- ACM-ICPC 2018 南京赛区网络预赛 E AC Challenge(状压dp)
Dlsj is competing in a contest with n (0 < n \le 20)n(0<n≤20) problems. And he knows the answe ...
- E. AC Challenge ACM-ICPC 2018 南京赛区网络预赛 状压dp + 枚举状态
博客目录 原题 题目链接 Dlsj is competing in a contest with n (0 < n \le 20)n(0<n≤20) problems. And he kn ...
最新文章
- 信息瓶颈提出者Naftali Tishby生前指导,129页博士论文「神经网络中的信息流」公布...
- qsort函数和sort函数
- python excel 自动化-python自动化测试报告(excel篇)
- 2017蓝桥杯 对局匹配(贪心)
- PE学习(三)第三章:PE文件头
- jQuery函数attr()和prop()的区别
- bootstrap怎么在移动端横向布局_移动端筛选中的「不限」到底该怎么用
- 经典算法问题——稳定匹配(Stable Matching)
- mapgis矢量化怎么打分数_mapgis矢量化错了如何后退一步
- Microsoft Visio 2010 - 直线连接线
- 怎样批量修改照片分辨率?
- 服务器pci数据捕获和信号处理控制器驱动,PCI数据捕获和信号处理控制器是哪个驱动...
- 解决w950播放RM视频的问题[转]
- 由递推关系式用差分方程的方法得到通项公式实现求斐波那契数列的第n项;迭代、递归、栈、差分方程之间的本质联系以及由推广的迭代法解决“变态青蛙跳台阶”问题;汉诺塔问题的数字特征以及用递归解决的原理推导。
- APP二维码下载 自动跳转
- 安卓版微信内置浏览器无法触发onchange事件
- Windows下解决依赖动态库问题:bat脚本实现自动复制dll文件
- CodeGear RAD Studio 2007下载
- alfafile中转站免费_中转站全集免费在线观看-手机看中转站HD完整版 - 穷TV_院线大片影视大全...
- 手怎么画?怎样才能画好人物的手部?