2018ACM-ICPC南京区域赛M---Mediocre String Problem【exKMP】【Manacher】
这题就单独写个题解吧。想了两天了,刚刚问了一个大佬思路基本上有了。
题意:
一个串$S$,一个串$T$,在$S$中选一段子串$S[i,j]$,在$T$中选一段前缀$T[1,k]$使得$S[i,j]T[1,k]$拼起来得到的字符串是回文,并且$S$的这个串长度大于$T$的这个。问有多少这样的三元组$(i,j,k)$
思路:
首先我们可以知道我们要找的其实就是这样三个串,$a,b,c$。其中$a$和$c$合起来是$S$中连续的一段子串,$b$在$T$中且$a$和$b$是对称的,$c$一定要是一个回文,且长度至少是$1$。
第一步比较简单我们可以用manacher求出$S$中的每一个回文。
比如上面图中的下面话的是一个以$i$为中心的回文,假设他的半径是$p$。
那么$i-p$到$i-1$都是满足条件的$a$串的起始点,因为他们后面都接着一段回文。
那么我们把$S$倒过来得到$S'$,拿$S'$和$T$跑exkmp,就可以得到$S'$的每一个后缀和$T$最长公共前缀。
这表示有$ex[i]$个串可以作为$a$串的选择。
答案应该是$a$串的选择个数$*c$串的选择个数
$c$串的选择个数怎么找呢,其实他就是以$i$为开头的回文串的个数。
用manacher加差分可以处理。具体的可以看hdu5157 https://www.cnblogs.com/wyboooo/p/9988397.html这道题。
对于$S$串的每一个下标$i$,$ex[lens - i - 1 + 1] = k$表示$S[i-1-k+1,i-1]$和$T[1,k]$对称。
由于我算$pre$数组的时候把下标往后挪了一个 所以每一个下标$i$的贡献是$ex[lens - i + 1] * pre[i]$
这个下标对应的算清楚,记得用上long long 就可以过啦!耶!
搞了两天我终于写出来了!
妈呀真的好激动啊!!!!!
#include<iostream>
//#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
//#include<cstdlib>
#include<cstring>
#include<algorithm>
//#include<queue>
#include<vector>
//#include<set>
//#include<climits>
//#include<map>
using namespace std;
typedef long long LL;
#define N 100010
#define pi 3.1415926535
#define inf 0x3f3f3f3f const int maxn = 1e6 + ;
char s[maxn], ss[maxn * ], t[maxn], s_rev[maxn];
LL pre[maxn * ];
int lens, lent, p[maxn * ]; int init()
{
ss[] = '$';
ss[] = '#';
int lenss = ;
for(int i = ; i < lens; i++){
ss[lenss++] = s[i];
ss[lenss++] = '#';
}
ss[lenss] = '\0';
return lenss;
} void manacher()
{
int lenss = init();
int id, mx = ;
for(int i = ; i < lenss; i++){
if(i < mx){
p[i] = min(p[ * id - i], mx - i);
}
else{
p[i] = ;
}
while(ss[i - p[i]] == ss[i + p[i]])p[i]++;
if(mx < i + p[i]){
id = i;
mx = i + p[i];
}
}
} int nxt[maxn],ex[maxn]; //ex数组即为extend数组
//预处理计算next数组
void GETNEXT(char *str)
{
int i=,j,po,len=strlen(str);
nxt[]=len;//初始化next[0]
while(str[i]==str[i+]&&i+<len)//计算next[1]
i++;
nxt[]=i;
po=;//初始化po的位置
for(i=;i<len;i++)
{
if(nxt[i-po]+i<nxt[po]+po)//第一种情况,可以直接得到next[i]的值
nxt[i]=nxt[i-po];
else//第二种情况,要继续匹配才能得到next[i]的值
{
j=nxt[po]+po-i;
if(j<)j=;//如果i>po+nxt[po],则要从头开始匹配
while(i+j<len&&str[j]==str[j+i])//计算next[i]
j++;
nxt[i]=j;
po=i;//更新po的位置
}
}
}
//计算extend数组
void EXKMP(char *s1,char *s2)
{
int i=,j,po,len=strlen(s1),l2=strlen(s2);
GETNEXT(s2);//计算子串的next数组
while(s1[i]==s2[i]&&i<l2&&i<len)//计算ex[0]
i++;
ex[]=i;
po=;//初始化po的位置
for(i=;i<len;i++)
{
if(nxt[i-po]+i<ex[po]+po)//第一种情况,直接可以得到ex[i]的值
ex[i]=nxt[i-po];
else//第二种情况,要继续匹配才能得到ex[i]的值
{
j=ex[po]+po-i;
if(j<)j=;//如果i>ex[po]+po则要从头开始匹配
while(i+j<len&&j<l2&&s1[j+i]==s2[j])//计算ex[i]
j++;
ex[i]=j;
po=i;//更新po的位置
}
}
} int main()
{ while(scanf("%s", s) != EOF){
scanf("%s", t);
lens = strlen(s);
lent = strlen(t);
for(int i = ; i <= lens * + ; i++){
pre[i] = ;
p[i] = ;
ex[i] = ;
}
manacher();
for(int i = lens * ; i >= ; i--){
int x = i / ;
pre[x]++;
pre[x - (p[i] / )]--;
}
for(int i = lens; i >= ; i--){
pre[i] += pre[i + ];
} for(int i = ; i <= lens; i++){
s_rev[i] = s[lens - - i];
}
EXKMP(s_rev, t);
LL ans = ;
/*for(int i = 1; i <= lens; i++){
cout<<pre[i]<<" "<<ex[i]<<endl;
}*/
for(int i = ; i <= lens; i++){
//if(ex[lens - i + 1])
ans += 1LL * ex[lens - i + ] * pre[i];
}
printf("%I64d\n", ans);
}
return ;
}
2018ACM-ICPC南京区域赛M---Mediocre String Problem【exKMP】【Manacher】的更多相关文章
- 【2013南京区域赛】部分题解 hdu4802—4812
上周末打了一场训练赛,题目是13年南京区域赛的 这场题目有好几个本来应该是我擅长的,但是可能是太久没做比赛了各种小错误代码写的也丑各种warusn trush搞得人很不爽 全场题之一的1002也没有想 ...
- 2015 ACM / ICPC 亚洲区域赛总结(长春站&北京站)
队名:Unlimited Code Works(无尽编码) 队员:Wu.Wang.Zhou 先说一下队伍:Wu是大三学长:Wang高中noip省一:我最渣,去年来大学开始学的a+b,参加今年区域赛之 ...
- Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细心讲解)
layout: post title: Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细 ...
- ACM-ICPC2018南京赛区 Mediocre String Problem
Mediocre String Problem 题解: 很容易想到将第一个串反过来,然后对于s串的每个位置可以求出t的前缀和它匹配了多少个(EXKMP 或者 二分+hash). 然后剩下的就是要处理以 ...
- 2018 ACM-ICPC南京区域赛题解
解题过程 开场开A,A题shl看错题意,被制止.然后开始手推A,此时byf看错E题题意,开始上机.推出A的规律后,shl看了E题,发现题意读错.写完A题,忘记判断N=0的情况,WA+1.过了A后,sh ...
- 2018ACM-ICPC南京区域赛---AJGIDKM
含[最小球覆盖][最大流isap]模板. 题面pdf https://codeforc.es/gym/101981/attachments/download/7891/20182019-acmicpc ...
- 2014ACM/ICPC亚洲区域赛牡丹江站汇总
球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...
- 2019 ICPC 上海区域赛总结
2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...
- HDU 4811 Ball -2013 ICPC南京区域现场赛
题目链接 题意:三种颜色的球,现给定三种球的数目,每次取其中一个放到桌子上,排成一条线,每次放的位置任意,问得到的最大得分. 把一个球放在末尾得到的分数是它以前球的颜色种数 把一个球放在中间得到的分数 ...
随机推荐
- 详解CentOS设置163的yum源的过程
转自启动CentOS系统,打开火狐浏览器,如下图所示: 2 登录“mirrors.163.com”,如下图所示: 3 点击centos后面的“centos使用帮助”,如下图所示: 4 可以看到设置和使 ...
- java 获取系统当前时间并格式化
java 获取系统当前时间并格式化 CreateTime--2018年5月9日11:41:00 Author:Marydon 实现方式有三种 updateTime--2018年7月23日09点32 ...
- orocos_kdl学习(一):坐标系变换
KDL中提供了点(point).坐标系(frame).刚体速度(twist),以及6维力/力矩(wrench)等基本几何元素,具体可以参考 Geometric primitives 文档. Creat ...
- openjudge noi 买房子
题目链接:http://noi.openjudge.cn/ch0105/16/ 总时间限制: 1000ms 内存限制: 65536kB 描述 某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平 ...
- 【C#】C#中方法(函数)的类型有哪些
目录结构: contents structure [+] 构造函数 引用类型的构造函数 值类型的构造函数 析构函数 析构函数的使用 析构函数和Dispose()方法的区别 操作符重载 转化操作符方法 ...
- opencv-android笔记1:android studio 2.3 + opencv-android-sdk 实现 camera预览
Android studio环境配置不再赘述,可以参照我的其他博客. Android应用程序开发环境搭建:http://blog.csdn.net/ja33son/article/details/61 ...
- SQL Server 数据库基础笔记分享(下)
前言 本文是个人学习SQL Server 数据库时的以往笔记的整理,内容主要是对数据库的基本增删改查的SQL语句操作和约束,视图,存储过程,触发器的基本了解. 注:内容比较基础,适合入门者对SQL S ...
- [AaronYang]那天有个小孩跟我说Js-NodeJS[AY0]-EJS
按照自己的思路学习Node.Js 随心出发.EJS是Node.js中express框架中使用的一个模版引擎,当然还有Jade 我的学习就靠网上查资料,没有买书系统学,自己整理,如果有用了哪位大神的代码 ...
- CentOS下如何查看并杀死僵尸进程
昨天服务器到期,之前的服务器由于空间小,不能满足现在的服务要求,就新购买了一个服务器,目前正在调试安装中! 在调试过程中,发现系统中有很多僵尸进程,现在就是找出这些僵尸进程,并将其杀死. 用top查看 ...
- latex学习(三)
本文记录一点杂事. 1.vim下有个实时pdf预览的插件:https://github.com/xuhdev/vim-latex-live-preview 2.实时预览pdf的pdf查看器是:evin ...