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南京区域现场赛
题目链接 题意:三种颜色的球,现给定三种球的数目,每次取其中一个放到桌子上,排成一条线,每次放的位置任意,问得到的最大得分. 把一个球放在末尾得到的分数是它以前球的颜色种数 把一个球放在中间得到的分数 ...
随机推荐
- 使用 cmake 进行交叉编译
cmake 因为“又”要额外学一门语言而被诟病,但这并不妨碍越来越多私人项目用 cmake 来管理:autoconfig 确实是更好的发行工具,但用 cmake 管理项目显然更加的容易.如果要应用这些 ...
- 前后分离模型之封装 Api 调用
Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过 ...
- Ubuntu菜鸟入门(十七)—— E: Sub-process /usr/bin/dpkg returned an error code (1) 出错解决方案
cd /var/lib/dpkg sudo mv info info.bak sudo mkdir infosudo apt-get install shotwel
- [Aaronyang] 写给自己的WPF4.5 笔记9[复杂数据处理三步曲,数据展示ListView泪奔2/3]
我的文章一定要做到对读者负责,否则就是失败的文章 --------- www.ayjs.net aaronyang技术分享 作者留言: 小小的推荐,作者的肯定,读者的支持. ...
- Jenkins Post Build网址
Hudson Post build taskhttps://plugins.jenkins.io/postbuild-taskThis plugin allows the user to execut ...
- Android Studio 运行出现 Multiple dex files define Landroid/support/annotation/AnimRes 解决方法
引入的工程的android-support-v4.jar版本跟自己工程的android-support-v4.jar的版本不一样
- java框架篇---hibernate之连接池
Hibernate支持第三方的连接池,官方推荐的连接池是C3P0,Proxool,以及DBCP.在配置连接池时需要注意的有三点: 一.Apche的DBCP在Hibernate2中受支持,但在Hiber ...
- 【iCore4 双核心板_ARM】例程十七:USB_MSC实验——读/写U盘(大容量存储器)
实验方法: 1.将跳线冒跳至USB_UART,通过Micro USB 线将iCore4 USB-UART接口与电脑相连. 2.打开PUTTY软件. 3.通过读U盘转接线将U盘(或者读卡器)与iCore ...
- vue深入相应式原理
Vue 最显著的特性之一便是不太引人注意的响应式系统(reactivity system).模型层(model)只是普通 JavaScript 对象,修改它则更新视图(view).这会让状态管理变得非 ...
- Java知多少(16)StringBuffer与StringBuider
String 的值是不可变的,每次对String的操作都会生成新的String对象,不仅效率低,而且耗费大量内存空间. StringBuffer类和String类一样,也用来表示字符串,但是Strin ...