HDU3068 马拉车 模拟版+标准版

讲解:

https://www.jianshu.com/p/392172762e55
https://blog.csdn.net/qq_43456058/article/details/94588721

模板代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e6+5;
int len, p[2 * N];
char s[N], str[2 * N];
void init() {
	len = strlen(s);
	int k = 0;
	str[k++] = '$';///str【0】
	for(int i = 0; i < len; i++) {
		str[k++] = '#';
		str[k++] = s[i];///一个#,一个字符
	}
	str[k++] = '#';///str[2*len+1]
	len = k;
	str[k]='@';///字符串尾,防止越界
}
int manacher() {
	int sum = 0, mx = 0, id;///mx为最右边,id为中心点
	for(int i = 1; i < len; i++)
    {
		if(i < mx) p[i] = min(mx - i, p[2 * id - i]);///判断这个点有没有超过mx
		else p[i] = 1;///超过就标记为1
		while(str[i - p[i]] == str[i + p[i]]) p[i]++;///判断当前点是不是最长回文子串,不断的向右扩展
		if(p[i] + i > mx)///p[i]+i 为最右边界
		{
			mx = p[i] + i;
			id = i;///更新中间点
		}
		sum = max(sum, p[i] - 1);///最长回文串长度
	}
	return sum;
}
int main() {
	while(~scanf("%s", s)) {
		init();
		printf("%d\n", manacher());
	}
	return 0;
}

模拟版代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e6+5;
int len, p[2 * N];
char s[N], str[2 * N];
void init() {
	len = strlen(s);
	int k = 0;
	str[k++] = '$';///str【0】
	for(int i = 0; i < len; i++) {
		str[k++] = '#';
		str[k++] = s[i];///一个#,一个字符
	}
	str[k++] = '#';///str[2*len+1]
	len = k;
	str[k]='@';///字符串尾,防止越界
	for(int i=0;i<=k;i++)
    {
        cout<<str[i];
        if(i>=10)cout<<"  ";
        else cout<<" ";
    }
    cout<<endl;
    for(int i=0;i<=k;i++)
    {
        cout<<i<<" ";
    }
    cout<<endl;
}
int manacher() {
	int sum = 0, mx = 0, id;///mx为最右边,id为中心点
	for(int i = 1; i < len; i++)
    {
        cout<<"i "<<i<<"  "<<"mx "<<mx<<endl;
		if(i < mx) p[i] = min(mx - i, p[2 * id - i]);///判断这个点有没有超过mx
		else p[i] = 1;///超过就标记为1
		cout<<"一。"<<"  "<<"i "<<i<<"  "<<"p[i] "<<p[i]<<endl;
		while(str[i - p[i]] == str[i + p[i]]) p[i]++;///判断当前点是不是最长回文子串,不断的向右扩展
		cout<<"二。"<<"  "<<"i "<<i<<"  "<<"p[i] "<<p[i]<<endl;
		if(p[i] + i > mx)///p[i]+i 为最右边界
		{
			mx = p[i] + i;
			id = i;///更新中间点
			cout<<"更新";
		}
		cout<<"三。"<<"  "<<"id "<<id<<"  "<<"mx "<<mx<<endl;
		sum = max(sum, p[i] - 1);///最长回文串长度
		cout<<"最长回文串长度--"<<sum<<endl;

		for(int j=0;j<=len;j++)
    {
        cout<<str[j];
        if(j>=10)cout<<"  ";
        else cout<<" ";
    }
    cout<<endl;
    for(int j=0;j<=len;j++)
    {
        cout<<j<<" ";
    }
    cout<<endl;
    for(int j=0;j<=len;j++)
    {
        cout<<p[j]<<" ";
    }
    cout<<endl<<endl;
	}
	return sum;
}
int main() {
	while(~scanf("%s", s)) {
		init();
		printf("%d\n", manacher());
	}
	return 0;
}

运行结果:

cabbaf
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
i 1  mx 0
一。  i 1  p[i] 1
二。  i 1  p[i] 1
更新三。  id 1  mx 2
最长回文串长度--0
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0

i 2  mx 2
一。  i 2  p[i] 1
二。  i 2  p[i] 2
更新三。  id 2  mx 4
最长回文串长度--1
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 0 0 0 0 0 0 0 0 0 0 0 0

i 3  mx 4
一。  i 3  p[i] 1
二。  i 3  p[i] 1
三。  id 2  mx 4
最长回文串长度--1
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 0 0 0 0 0 0 0 0 0 0 0

i 4  mx 4
一。  i 4  p[i] 1
二。  i 4  p[i] 2
更新三。  id 4  mx 6
最长回文串长度--1
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 0 0 0 0 0 0 0 0 0 0

i 5  mx 6
一。  i 5  p[i] 1
二。  i 5  p[i] 1
三。  id 4  mx 6
最长回文串长度--1
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 0 0 0 0 0 0 0 0 0

i 6  mx 6
一。  i 6  p[i] 1
二。  i 6  p[i] 2
更新三。  id 6  mx 8
最长回文串长度--1
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 0 0 0 0 0 0 0 0

i 7  mx 8
一。  i 7  p[i] 1
二。  i 7  p[i] 5
更新三。  id 7  mx 12
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 0 0 0 0 0 0 0

i 8  mx 12
一。  i 8  p[i] 2
二。  i 8  p[i] 2
三。  id 7  mx 12
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 0 0 0 0 0 0

i 9  mx 12
一。  i 9  p[i] 1
二。  i 9  p[i] 1
三。  id 7  mx 12
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 0 0 0 0 0

i 10  mx 12
一。  i 10  p[i] 2
二。  i 10  p[i] 2
三。  id 7  mx 12
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 0 0 0 0

i 11  mx 12
一。  i 11  p[i] 1
二。  i 11  p[i] 1
三。  id 7  mx 12
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 0 0 0

i 12  mx 12
一。  i 12  p[i] 1
二。  i 12  p[i] 2
更新三。  id 12  mx 14
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 2 0 0

i 13  mx 14
一。  i 13  p[i] 1
二。  i 13  p[i] 1
三。  id 12  mx 14
最长回文串长度--4
$ # c # a # b # b # a  #  f  #  @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 2 1 0

4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值