最长回文字串(马拉车算法)
题目一
https://blog.csdn.net/qq_16554583/article/details/79763296
模板题:
1032 : 最长回文子串
Time Limit:1000ms
Case Time Limit:1000ms
Memory Limit:256MB
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
提示一 提示二 提示三 提示四- Sample Input
-
3 abababa aaaabaa acacdas
- Sample Output
-
7 5 3
题目二:
这个题就是如果字串中有长度为偶数的字串的话就输出Or not,否者就输出Odd,就是这样
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn = 1e6 + 5; char s[maxn * 2], str[maxn * 2]; int Len[maxn * 2], len; void getstr() {//重定义字符串 int k = 0; str[k++] = '@';//开头加个特殊字符防止越界 for (int i = 0; i < len; i++) { str[k++] = '#'; str[k++] = s[i]; } str[k++] = '#'; len = k; str[k] = 0;//字符串尾设置为0,防止越界 } int manacher(){ int mx = 0, id;//mx为最右边,id为中心点 int maxx = 0; for (int i = 1; i < len; i++) { if (mx > i) Len[i] = min(mx - i, Len[2 * id - i]);//判断当前点超没超过mx else Len[i] = 1;//超过了就让他等于1,之后再进行查找 while (str[i + Len[i]] == str[i - Len[i]]) Len[i]++;//判断当前点是不是最长回文子串,不断的向右扩展 if (Len[i] + i > mx) {//更新mx mx = Len[i] + i; id = i;//更新中间点 int p=Len[i]-1;//这个p就是回文串的长度 //cout<<str[id]<<" "<<str[id-p+1]<<" "<<p<<endl; if(p!=0&&p%2==0){ //cout<<str[id]<<" "<<Len[i]-1<<endl; return 0; } } } return 1; } int main() { int n; cin>>n; scanf("%s", s); len = strlen(s); getstr(); //cout<<str<<endl; if(manacher()){ cout<<"Odd."<<endl; } else{ cout<<"Or not."<<endl; } return 0; }
题目三
这也是一个模板题
给定一个长度为 n 的由小写字母构成的字符串,求它的最长回文子串的长度是多少
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 2e7 + 10; int n; char a[N], b[N]; int p[N]; void init() { int k = 0; b[k ++ ] = '$', b[k ++ ] = '#'; for (int i = 0; i < n; i ++ ) b[k ++ ] = a[i], b[k ++ ] = '#'; b[k ++ ] = '^'; n = k; } void manacher() { int mr = 0, mid; for (int i = 1; i < n; i ++ ) { if (i < mr) p[i] = min(p[mid * 2 - i], mr - i); else p[i] = 1; while (b[i - p[i]] == b[i + p[i]]) p[i] ++ ; if (i + p[i] > mr) { mr = i + p[i]; mid = i; } } } int main() { scanf("%s", a); n = strlen(a); init(); manacher(); int res = 0; for (int i = 0; i < n; i ++ ) res = max(res, p[i]);//最后回文串的长度就是p[i]-1 printf("%d\n", res - 1); return 0; }