字符串学习笔记

时间:2021-07-12
本文章向大家介绍字符串学习笔记,主要包括字符串学习笔记使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1. manacher 马拉车

P3805 【模板】manacher 算法

思路

  1. 回文串长度有奇有偶,奇回文串有对称中心,那偶回文串呢,所以我们就在每两个字符串之间加一个#,再在整个串前面加一个 % ,这样奇偶串就可以用按一种方法处理了,比如abcd --> %a#b#c#d#
  2. 我们可以用O(n) 求出r数组,r[i]是以i为对称中心的回文串半径(长度包括i),令mx是回文串覆盖的最右边界的右边一位,p是覆盖最右边界的回文串的对称中心,这时我们要求r[i],暴力会TLE,当p<mx时,我们考虑r[i]可以从r[2 * p - i] 处已确认对称的部分转移过来,r[i]=min (mx-p,r[ 2 * p - i ]),之后继续尝试暴力向外拓展,看r[i]是否能增大

code

#include<bits/stdc++.h>
#define N 22000010
#define mod 998244353
#define int long long
using namespace std;
int n,ans;
int r[N];
char a[N];
template<class T> inline void read(T &x)
{
	x=0;int g=1;char s=getchar();
	for (;s<'0'||s>'9';s=getchar()) if (s=='-') g=-1;
	for (;s>='0'&&s<='9';s=getchar()) x=(x<<1)+(x<<3)+(s^48);
	x*=g;
}
signed main()
{
	int i,j,op,x,y,z;
	scanf("%s",a+1);
	n=strlen(a+1);
	for (i=n;i;i--) a[2*i]=a[i],a[2*i+1]='#';a[1]='#';a[0]='$';	
	int p=1,mx=1;
	n=2*n+1;
	for (i=1;i<=n;i++)
	{
		if (mx<=i) r[i]=1;
		else r[i]=min(mx-i,r[2*p-i]);
		while(a[i+r[i]]==a[i-r[i]]) r[i]++;
		if (i+r[i]>mx)
		{
			mx=i+r[i];p=i;
		}	
		ans=max(ans,r[i]);
	}
	printf("%lld\n",ans-1);
	return 0;
}

原文地址:https://www.cnblogs.com/Ritalc/p/15003831.html