首页 > 其他分享 >字符串【下】

字符串【下】

时间:2023-12-24 22:44:49浏览次数:196  
标签:rt 10 return int void 字符串 inline

\(\color{white}{P5546 最长公共子串}\)

把字符串拼起来,也就是用 # 连接,然后在上面做最长重复且属于所有串的后缀均出现过的子串。也就是满足以下条件的子串

  1. 重复过

  2. 其中包含的后缀可以覆盖所有的串

这样的子串是合格的。要求求得一个最长的串满足上述条件。

最长也就是要求最大化 \(\min\{h[k]\} _{i < k \leq j}\) 而且要使第二个条件满足。

上面式子是单调不升的,所以最小化 \(j-i\) ,显然这是可以通过 two-pointer 维护的,而 2. 条件可以用类似莫队或者用前缀和维护,至于查询 \(\min\) ,滑动窗口、线段树、st 均可。这里选用线段树。因为很好写。

然后直接算就行了。

复杂度看似十分玄学,实际上瓶颈还是在于前面求 \(h\) 数组的 \(\mathcal{O(nlog^2n)}\),写出来就可以 \(ac.\) 主要要注意上面的 \(<\) 符号,很容易被阴。

$\text{code}$
// Qx 's data
#include <bits/stdc++.h>
#define ll long long
using std::cin;
using std::cout;
using std::cerr;
const int N=20005,Time=10,inf=0x3f3f3f3f;
int T,n,w;
char ch[N*5];
int ed[Time+5];
int rk[N*10],sa[N*10],rk0[N*10];
int h[N*5];
char s[10][N];
int col[N*10],vis[N*10];
inline int gf(int x){
	return vis[x];
}
inline void _sa(void){
	for(int i=1;i<=n;++i)
		rk[i]=ch[i],sa[i]=i;
	for(w=1;w<=n;w<<=1){
		std::stable_sort(sa+1,sa+n+1,[](int x,int y){
			return rk[x]==rk[y]?rk[x+w]<rk[y+w]:rk[x]<rk[y];
		});
		int cnt=0;
		memcpy(rk0,rk,sizeof rk);
		for(int i=1;i<=n;++i){
			if(rk0[sa[i]]==rk0[sa[i-1]] &&
				rk0[sa[i]+w]==rk0[sa[i-1]+w])
			rk[sa[i]]=cnt;
			else
			rk[sa[i]]=++cnt;
		}
	}
}
inline void _h(void){
	int k=0;
	for(int i=1;i<=n;++i)
		rk[sa[i]]=i;
	for(int i=1;i<=n;++i){
		if(k) --k;
		int j=sa[rk[i]-1];
		while(ch[i+k]==ch[j+k] && ch[i+k]!='#') ++k;
		h[rk[i]]=k;
	}
	return;
}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
#define lson ls,l,mid
#define rson rs,mid+1,r
struct segtree{
	int tree[N*40];
	inline void pushup(int rt,int l=0,int r=0){
		return tree[rt]=std::min(tree[ls],tree[rs]),void();
	}
	int query(int rt,int l,int r,int L,int R){
		if(L<=l && r<=R) return tree[rt];
		int res=inf;
		if(L<=mid) res=std::min(res,query(lson,L,R));
		if(R> mid) res=std::min(res,query(rson,L,R));
		return res;
	}
	void Build(int rt,int l,int r){
		if(l==r) return tree[rt]=h[l],void();
		Build(lson) , Build(rson);
		return pushup(rt,l,r),void();
	}
}G;
int l=0,r=0,cs=0,ans=-inf;
inline void add(int x){
	if(!x) return;
	++col[x];
	if(col[x]==1) ++cs;
}
inline void del(int x){
	if(!x) return;
	--col[x];
	if(col[x]==0) --cs;
}
inline void buildvis(void){
	for(int i=1;i<=T;++i){
		for(int j=ed[i-1]+1;j<ed[i];++j)
			vis[rk[j]]=i;
	}
		
}
inline void two_pointer(void){
	_sa(),_h();
	G.Build(1,1,n);
	buildvis();
	l=r=1;
	add(gf(1));
	while(r<=n){
		if(cs==T){
			while(cs==T)del(gf(l)),++l;
			--l,add(gf(l));
			ans=std::max(ans,G.query(1,1,n,l+1,r));
		}
		++r;
		add(gf(r));
	}
	printf("%d\n",ans);
} 
int main(){
	cin>>T;
	for(int i=1;i<=T;++i) cin>>(s[i]+1);
	for(int i=1;i<=T;++i) ed[i]=ed[i-1]+strlen(s[i]+1)+1;
	for(int i=1;i<=T;++i){
		int len=strlen(s[i]+1);
		for(int j=1;j<=len;++j)
			ch[++n]=s[i][j];
		ch[++n]='#';
	}
	--n;
	two_pointer(); 
}

标签:rt,10,return,int,void,字符串,inline
From: https://www.cnblogs.com/QxBlogs/p/string_2.html

相关文章

  • CSP-S 2023消消乐 字符串哈希做法and链表优化dp做法
    做完这题感觉整个人都升华了...打算说一下两种做法,字符串哈希和dp均可。dp则需要维护一个前向星去检索出第一个符合要求的位置。题解明天补,先写高数了。#include<bits/stdc++.h>#defineintlonglong#defineullunsignedlonglong#definerep(i,a,b)for(inti=(a);i<......
  • C++ Qt开发:字符串QString容器
    在Qt框架中,QString是一个强大而灵活的字符串容器,专为处理Unicode字符而设计。它提供了许多方便的方法来操作和处理字符串,使得在跨平台开发中能够轻松地进行文本操作。QString是Qt开发中不可或缺的一部分,它的灵活性和强大的功能使其成为处理文本和字符串操作的理想选择。本篇......
  • mysql 判断字符串结尾
    mysql判断字符串结尾CREATETABLE`tbl_str`(`id`INTDEFAULTNULL,`Str`VARCHAR(30)DEFAULTNULL)INSERTINTO`mytest`.`tbl_str`(`id`,`Str`)VALUES('1','helloworld'),('2','mysqlstring'),('3','......
  • 性能篇:字符串性能优化不容小觑
    嗨,大家好!我是小米,一个热衷于技术分享的小伙伴。今天,我们一起来聊一聊在Java中如何优化字符串性能,探讨一些令人激动的方法,让你的程序在处理字符串时更加高效!为什么String设计为不可变性?首先,让我们谈谈为什么Java中的String被设计为不可变性。这并不是偶然的决定,而是经过深思熟虑的。......
  • [LeetCode Hot 100] LeetCode394. 字符串解码
    题目描述思路思路:碰到数字:压入数字栈,注意多位数的情况碰到字母:直接拼接到res遇到[:将num和res分别压入栈遇到]:开始处理栈顶元素方法一:classSolution{publicStringdecodeString(Strings){intnum=0;StringBuilderres=newStringBuil......
  • 字符函数和字符串函数:strcmp、strncpy——《初学C语言第37天》
    //////————strcmp(比较两个字符串(的内容,ASCII值))————>头文件#include<string.h>//第一个字符串大于第二个字符串,则返回大于0的数字//第一个字符串等于第二个字符串,则返回0//第一个字符串小于第二个字符串,则返回小于0的数字//那么如何判断两个字符串?//比较方法:下标逐步......
  • java 判断字符串a中包好几个字符串b
    Java判断字符串a中是否包含字符串b在Java编程中,我们经常需要判断一个字符串是否包含另一个字符串。这种需求在很多实际场景中都会遇到,比如搜索功能、数据过滤等。本文将介绍如何使用Java判断一个字符串中是否包含多个子字符串,并给出相关代码示例。方案一:使用String类的contains方......
  • Python JSON格式字符串与对象之间的转换多种方法
    ​ 1、json.dumps()和json.loads()方法使用 json.dumps() 方法将Python对象转换为JSON格式字符串。使用 json.loads() 方法将JSON格式字符串解析为Python对象。使用示例:PythonJSON格式字符串与对象之间的转换多种方法-CJavaPy2、json.dump()和json.load(......
  • 代码随想录算法训练营第十一天|20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150
    一、20.有效的括号题目链接:LeetCode20.有效的括号学习前:思路:当前元素为左括号,直接入栈当前元素为右括号,若找到对应的左括号匹配,则循环继续;反之返回false若栈为空,返回true;反之false时间复杂度:O(n)空间复杂度:O(n)学习后:采用入栈右括号,降低复杂度。即当遇到左......
  • 字符函数和字符串函数:strcpy、strcat——《初学C语言第36天》
    ////strcat(字符串追加)——>头文件:<string.h>//strcat的功能就是:1.先找到目标字符串的结尾(\0)然后进行2.strcpy拷贝//char*strcat(char*destination,constchar*source)//括号里为两个地址,返回类型char*//destination目的地 source源头,把源头的数据追加到目的地空间的末......