马拉车入门参考博客及例题汇集

参考博客
知乎
模板
回文串的半径各种情况的证明+例题

例题
最长回文(模板题)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map> 
using namespace std;
const int mn=1e6+5;
char str[mn],tmp[mn*2];
int len[mn*2];
//转化字符串
int init(char *st)
{
 	int i,Len=strlen(st);
 	tmp[0]='@';
	 for(int i=1;i<=2*Len;i+=2)
	 {
		  tmp[i]='#';
		  tmp[i+1]=st[i/2];
	 }
	 tmp[2*Len+1]='#';
	 tmp[2*Len+2]='$';
	 tmp[2*Len+3]=0;
	 return 2*Len+1;
}

int manacher(char *st,int Len)
{
	int mx=0,ans=0,po=0;
	for(int i=1;i<=Len;i++)
	{
		//计算len[i]初始值
		 if(mx>i) len[i]=min(mx-i,len[2*po-i]);//i+len[2*po-i]>mx,则len[i]=mx-i,
		 					//这一步第三个参考博客中回文半径的各种情况的讨论有解释
		  else len[i]=1;
		  
		  while(st[i-len[i]]==st[i+len[i]]) len[i]++;//拓展len[i]
		 
		  if(i+len[i]>mx){//更新po和mx
			   mx=len[i]+i;
			   po=i;
		  }
		  ans=max(ans,len[i]);
	 }
	 return ans-1;
}
int main()
{
	while(~scanf("%s",str))
	 {
		  int Len=init(str);
		  int res=manacher(tmp,Len);
		  printf("%d\n",res);
	 }
	  return 0;
}

奇数、偶数长度回文串
由于题目要找的是长度为M的回文,一开始以为只要有长度大于M的回文即可,实际上要分奇数长度和偶数长度的情况。举个例子,如果一个字符串有一个最长长度为8的回文,那么这个长度为8的回文可以删去首尾得到长度为6、4、2的回文,而得不到长度为3、5、7的回文,因此要分奇数长度和偶数长度,偶数长度找’#'位的半径,奇数则找字母位的半径。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map> 

using namespace std;
const int mn=1e6+5;
char str[mn],tmp[mn*2];
int len[mn*2];
int n,k;
//模板
int init(char *st)
{
	 int i,Len=strlen(st);
	 tmp[0]='@';
	 for(int i=1;i<=2*Len;i+=2)
	 {
		  tmp[i]='#';
		  tmp[i+1]=st[i/2];
	 }
	 tmp[2*Len+1]='#';
	 tmp[2*Len+2]='$';
	 tmp[2*Len+3]=0;
	 return 2*Len+1;
}
void manacher(char *st,int Len)
{
	 int mx=0,ans=0,po=0;
	 for(int i=1;i<=Len;i++)
	 {
		  if(mx>i) len[i]=min(mx-i,len[2*po-i]);
		  else len[i]=1;
		  while(st[i-len[i]]==st[i+len[i]]) len[i]++;
		  if(i+len[i]>mx){
		   mx=len[i]+i;
		   po=i;
		  }
	 }
}
	
int main()
{
 scanf("%d%d",&n,&k);
 scanf("%s",str);
 int Len=init(str);
 manacher(tmp,Len);
 int sign=0;
 if(k%2){
  for(int i=2;i<=Len;i+=2){
   if(len[i]-1>=k){
    sign=1;
    break;
   }
  }
  if(sign) printf("Accept");
  else printf("Reject");
 }else{
  for(int i=3;i<=Len;i+=2){
   if(len[i]-1>=k){
    sign=1;
    break;
   }
  }
  if(sign) printf("Accept");
  else printf("Reject");
 }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值