首页 > 其他分享 >【GJOI 2023.11.13 T2】 字符串匹配

【GJOI 2023.11.13 T2】 字符串匹配

时间:2023-11-14 20:56:30浏览次数:33  
标签:13 le int 2023.11 T2 long 3000005 d2 d1

字符串匹配

题意:给出两个字符串 \(a,b\) ,求:

\[\sum_{1 \le l \le r\le n} \sum_{l\le i \le j\le r}(a[l...r] 回文)(a[i...j]==b) \times (r-l+1) mod 2 \]

其中 \(n,m \le 10^6\) 。

解题思路

首先,因为 \(a[l..r]\) 长度为奇数,它又要回文,所以它一定是要有一个回文中心的。
那我们可以先用马拉车算法求出以一个节点为中心的最大回文半径,再用 \(KMP\) 求出 \(b\) 在 \(a\) 中哪里出现过,最后就看 \(b\) 在 \(a\) 中时被回文串一共包含多少次。
对于这个东西,我们可以先用树状数组做,但这样做会被卡常。
我们就可以用前缀和来代替,对于每个节点,考虑在其前半个字符串的 \(b\) 以及在其后半个字符串的 \(b\) ,用前缀和 \(v_i\) 与前缀和 \(i\times v_i\) 来解决。
时间复杂度 \(O(n)\) 。

Code

#include<bits/stdc++.h>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
const long long mod=4294967296;
int n,m,d[3000005],nxt[3000005],f[6000005],g;
long long f1[6000005],d1[3000005],d2[3000005];
bool v[3000005];
string a,b;
int lowbit(int x)
{
	return x&(-x);
}
void next()
{
	nxt[0]=-1;
	int x=1,y=-1;
	while(x<b.size())
	{
		while(y>=0&&b[x]!=b[y+1])y=nxt[y];
		if(b[x]==b[y+1])y++;
		nxt[x]=y;
		x++;
	}
	return;
}
void KMP()
{
	next();
	int x=0,y=-1;
	while(x<a.size())
	{
		while(y>=0&&(y==m-1||a[x]!=b[y+1]))y=nxt[y];
		if(a[x]==b[y+1])y++;
		if(y==m-1)v[x-y]=true;
		x++;
	}
	return;
}
int main()
{
	long long s=0,y=0;
	int x=0,p=0,mid;
	scanf("%d%d",&n,&m);
	g=n*2;
	cin>>a>>b;
	a=' '+a;
	for(int i=1;i<a.size();i++)
	{
		if(x+d[x]>=i)d[i]=min(d[x*2-i],d[x]+x-i);
		while(d[i]<i&&i+d[i]<a.size()-1&&a[i-d[i]-1]==a[i+d[i]+1])d[i]++;
		if(x+d[x]<i+d[i])x=i;
	}
	KMP();
	for(int i=1;i<=n;i++)
	{
		d1[i]=d1[i-1]+v[i];
		d2[i]=d2[i-1]+v[i]*i;
	}
	for(int i=1;i<=n;i++)
	{
		x=i-d[i],y=i+d[i]-m+1;
		mid=(x+y)>>1;
		if(x>y)continue;
		s+=(d2[mid]-d2[x-1])-(d1[mid]-d1[x-1])*(x-1);
		if(x!=y)s+=(y+1)*(d1[y+1]-d1[mid])-(d2[y+1]-d2[mid]);
		s%=mod;
	}
	printf("%lld",s);








  return 0;
}

标签:13,le,int,2023.11,T2,long,3000005,d2,d1
From: https://www.cnblogs.com/dijah/p/17832486.html

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (135)-- 算法导论11.3 1题
    一、用go语言,假设我们希望查找一个长度为n的链表,其中每一个元素都包含一个关键字k并具有散列值h(k)。每一个关键字都是长字符串。那么在表中查找具有给定关键字的元素时,如何利用各元素的散列值呢?文心一言:在Go语言中,你可以通过使用一个哈希表来存储关键字的散列值,并在查找具有给......
  • 文心一言 VS 讯飞星火 VS chatgpt (135)-- 算法导论11.3 1题
    一、用go语言,假设我们希望查找一个长度为n的链表,其中每一个元素都包含一个关键字k并具有散列值h(k)。每一个关键字都是长字符串。那么在表中查找具有给定关键字的元素时,如何利用各元素的散列值呢?文心一言:在Go语言中,你可以通过使用一个哈希表来存储关键字的散列值,并在查找具有......
  • 设计模式实验12实验13
    外观模式 packagetest12;publicclassMemory{publicvoidcheck(){System.out.println("内存自检");}}packagetest12;publicclassHardDisk{publicvoidread(){System.out.println("硬盘读取");}}packa......
  • 13、SpringMVC之异常处理器
    13.1、环境搭建创建名为spring_mvc_exception的新module,过程参考9.1节和9.5节13.1.1、创建错误提示页<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>错误页面&l......
  • P5513 [CEOI2013] Board CWOI1114C
    70分做法非常容易想到,使用高精度对经过的点编号,令\(pos\)为点的编号,初始为\(1\),则:1:\(pos<<=1\)2:\(pos<<=1|1\)U:\(pos>>=1\)L:\(pos--\)R:\(pos++\)#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e5+5,i......
  • 软件设计Tutorial 13_享元模式
    [实验任务一]:围棋设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。实验要求:1. 提交类图;  2.提交源代码;3.注意编程规范;4.要求用简单工厂模式和单例模式实现享元工厂类的设计。 packageXiang;publicclassBla......
  • 【洛谷 P1307】[NOIP2011 普及组] 数字反转 题解(字符串)
    [NOIP2011普及组]数字反转题目描述给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2)。输入格式一个整数。输出格式一个整数,表示反转后的新数。样例#1样例输入#1123样......
  • SpringBoot2和SpringBoot3有什么区别
    SpringBoot2和SpringBoot3有什么区别1.最低环境的区别Java版本:SpringBoot2的最低版本要求为Java8,支持Java9;而SpringBoot3决定使用Java17作为最低版本,并支持Java19。SpringFramework版本:SpringBoot2基于SpringFramework5开发;而SpringBoot3构建基于SpringFramework6之上。......
  • XPT2046
    XPT2046是一种典型的逐次逼近型模数转换器(SARADC),包含了采样/保持、模数转换、串口数据输出等功能。(采样:将一个时间上连续变化的模拟量转化为时间上离散的变化量。 保持:将采样结果存储起来,知道下次采样。 数模转换包含量化和编码。量化:将采样电平归化与之接近的离散数字电平......
  • 11月13数组以及数组常用发法
    目录1.数组2.数据的常用方法1.length方法2.push方法3.pop方法4.unshift方法5.shift方法6.slice方法7.reverse方法8.join方法9.concat方法10.sort方法特殊情况解决特殊情况的方法11.forEach方法12.splice方法null13.map方法还有用for循环取值1.数组数组的作用:使用单独的变量名来......