这题就单独写个题解吧。想了两天了,刚刚问了一个大佬思路基本上有了。

题意:

一个串$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】的更多相关文章

  1. 【2013南京区域赛】部分题解 hdu4802—4812

    上周末打了一场训练赛,题目是13年南京区域赛的 这场题目有好几个本来应该是我擅长的,但是可能是太久没做比赛了各种小错误代码写的也丑各种warusn trush搞得人很不爽 全场题之一的1002也没有想 ...

  2. 2015 ACM / ICPC 亚洲区域赛总结(长春站&北京站)

    队名:Unlimited Code Works(无尽编码)  队员:Wu.Wang.Zhou 先说一下队伍:Wu是大三学长:Wang高中noip省一:我最渣,去年来大学开始学的a+b,参加今年区域赛之 ...

  3. Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细心讲解)

    layout: post title: Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细 ...

  4. ACM-ICPC2018南京赛区 Mediocre String Problem

    Mediocre String Problem 题解: 很容易想到将第一个串反过来,然后对于s串的每个位置可以求出t的前缀和它匹配了多少个(EXKMP 或者 二分+hash). 然后剩下的就是要处理以 ...

  5. 2018 ACM-ICPC南京区域赛题解

    解题过程 开场开A,A题shl看错题意,被制止.然后开始手推A,此时byf看错E题题意,开始上机.推出A的规律后,shl看了E题,发现题意读错.写完A题,忘记判断N=0的情况,WA+1.过了A后,sh ...

  6. 2018ACM-ICPC南京区域赛---AJGIDKM

    含[最小球覆盖][最大流isap]模板. 题面pdf https://codeforc.es/gym/101981/attachments/download/7891/20182019-acmicpc ...

  7. 2014ACM/ICPC亚洲区域赛牡丹江站汇总

    球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...

  8. 2019 ICPC 上海区域赛总结

    2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...

  9. HDU 4811 Ball -2013 ICPC南京区域现场赛

    题目链接 题意:三种颜色的球,现给定三种球的数目,每次取其中一个放到桌子上,排成一条线,每次放的位置任意,问得到的最大得分. 把一个球放在末尾得到的分数是它以前球的颜色种数 把一个球放在中间得到的分数 ...

随机推荐

  1. Spark机器学习(2):逻辑回归算法

    逻辑回归本质上也是一种线性回归,和普通线性回归不同的是,普通线性回归特征到结果输出的是连续值,而逻辑回归增加了一个函数g(z),能够把连续值映射到0或者1. MLLib的逻辑回归类有两个:Logist ...

  2. Python多进程库multiprocessing中进程池Pool类的使用[转]

    from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...

  3. B+树索引和哈希索引的区别[转]

    导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...

  4. 检查死锁与Locked ownable synchronizers(转载)

    通过jstack可快速检查线程的死锁信息,用法如下: # 获取JVM ID(JAVA 进程ID),通过参数lv可以获取更详细的JAVA方法调用信息 jps -lv # 得到JVM ID后,执行jsta ...

  5. C#-MVC开发微信应用(3)--文本消息和图文消息的应答

    最近咨询微信的人很多,感觉这块也是一块商机,也为了演示SNF快速开发平台的优势,就用SNF快速开发平台开发出一套微信应用程序.使用<SNF.CodeGenerator>代码生成工具可以节省 ...

  6. Bash 中的特殊字符大全【转】

    Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...

  7. Docker 使用Docker知识简易部署一个LNMP平台

    1.自定义网络 docker network create lnmp 2.创建Mysql数据库容器(这里我们首先得创建一个mysql-vol数据卷) docker volume create mysq ...

  8. EasyUI - DataGrid 去右边空白滚动条列

    在网上查了很长时间没有找到解决方法,干脆自已查看一下代码来解决吧,随是压缩过的,不过也还是好查的,工夫不负有心人,终于解决了,方法如下: 一.我们先让表格自适应宽度 <!DOCTYPE html ...

  9. [k8s]一些技巧性的yaml和dockerfile-docker学习思路

    我会把一些dockerfile和yaml的技巧性东西不定期搜集到这里 docker学习思路 三部曲: 1,vm会搭建服务 2,docker会跑服务 3,k8s集群会调度该服务 存储 vm1 vm2 共 ...

  10. 【iCore1S 双核心板_FPGA】例程十二:基于单口RAM的ARM+FPGA数据存取实验

    实验现象: 核心代码: module single_port_ram( input CLK_12M, input WR, input RD, input CS0, inout [:]DB, input ...