HDU - 3294 Girls‘ research(manacher模板题)

题目链接

题目大意: 先给一个字符ch,表示ch是’a’,由此得出一个字符转化定义(即 :ch-'a’是相位差,其余字符也要按相位差移动,具体处理可以看代码),再给一个由小写字母组成的字符串,要求把字符串中字母全部按给出定义转化一下,最后求出转化后的字符串,最大回文子串。

思路:先处理一下字符串,然后manacher算法跑一下,记录最大回文串的中点位置即可,相关细节都在代码里面

#include
#include
#include
#include
#include
#include
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi acos(-1)
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
const int MAX=2e5+10;

void manacher(string s)
{
	int len=s.size();
	string str="$#";
	for(int i=0;i<len;i++)
	{
		str+=s[i];
		str+='#';
	}
	int len2=2*len+1;
    int p[MAX*2];//设p[i]为str中,以i为中心的最大回文串半径
    int id=0,mx=0;
    int ans=-1;
	int index=-1;//index是回文串的中心,如果是偶数的话,是中间偏左元素的位置
    for(int i=1;i<=len2;i++)
    {
        int left_i=2*id-i;//i关于id的轴对称点,利用他来加速查找
        if(i<mx) p[i]=min(p[left_i],mx-i);//首先是最大不能超过mx-i,再更具id左右对称,left_i的就是i的
        else p[i]=1;
        while(str[i-p[i]]==str[i+p[i]]) p[i]++;//右边界是'\0'所以不用特判
        if(mx<i+p[i])
        {
            id=i;
            mx=i+p[i];
        }   
        if(p[i]-1>ans)
		{
			ans=p[i]-1;
			index=i;
		}
    }
	if(ans<2) cout<<"No solution!"<<'\n';
	//s中的i号元素 ,在str中是2*(i+1)
	//接下来只要求出回文串在原串的开头下标就ok了
	else if(str[index]=='#')//index必为奇数
	{	
		int begin=index/2-ans/2;//关于开头位置可以在草稿纸上手算一下
		cout<<begin<<' '<<begin+ans-1<<'\n'<<s.substr(begin,ans)<<'\n';
		//依次是 开头  末尾  回文串
	}
	else
	{
		int begin=index/2-1-ans/2;
		cout<<begin<<' '<<begin+ans-1<<'\n'<<s.substr(begin,ans)<<'\n';
	}	
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);//这里不关同步流会tle
    char trie[27]="abcdefghijklmnopqrstuvwxyz";//预处理一个字母表
	char ch;
	string s;
	while(cin>>ch>>s)
	{
		int len=s.size();
		int ex=ch-'a';//相位差
		for(int i=0;i<len;i++)
		{
			s[i]=trie[(s[i]-'a'+26-ex)%26];//trie[25]=='z',超过25就要重新数,所以%26,建议手算验证一下
		}
		manacher(s);
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(字符串,算法)