NSWOJ 1228 && NYOJ 132 最长回文子串
来源:互联网 发布:手机u盘数据恢复 编辑:程序博客网 时间:2024/06/05 04:41
给你一个字符串 让你求最长回文子串 、
个人认为 如果你想尝试用一般的方法 写这道题 需要注意的点有
1 回文长度为1
2 回文分为奇数长度和偶数长度两种 如果你没用马拉车算法 这个地方很容易出bug
这道题讨厌的地方在忽略标点 需要你开另一个数组存储真正求回文的字符串
刚开始我写的非常繁琐 因为要记录字符的对应位置什么的 开了很多变量来储存这些信息
第一次a这道题的代码 是枚举每一个点 然后从这个点找出围绕改点的最长回文 维护一个最大值 大概这样 的东西
由于 用了很多函数 或者说 自己代码风格比较差还是什么原因 写的很冗长但是 时间是 4ms
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define debug() printf("GG~~\n")using namespace std;const int N = 5005;char str[N];int maxn , L , R, length;inline bool check(int x){ if(x < 0 || x >= length)return false; else return true;}int FindLeft(int x,int p)//第二个参数的意思是 在寻找点的时候是否包括x点 { int deviation = p; if(x - deviation < 0)return -1; while (check(x - deviation)) { if(isalpha(str[x - deviation]))return x - deviation; else deviation ++; if(x - deviation < 0)return -1; } return -1;}int FindRight(int x,int p){ int deviation = p; if(x + deviation >= length)return -1; while (check(x + deviation)) { if(isalpha(str[x + deviation])) return x + deviation; else deviation ++; if(x + deviation > length) return -1; } return -1;}bool judge(char a,char b){ if(a >= 'A' && a <= 'Z')a = a - 'A' + 'a'; if(b >= 'A' && b <= 'Z')b = b - 'A' + 'a'; if(a == b)return true; else return false;}void lps(int pos){ //奇数时 双向发散 int l = FindLeft(pos, 1), r = FindRight(pos, 1); int res = 1; while (true) {//奇数 双向发散 // if(r == -1)debug(); if(l == -1 || r == -1)break; if(judge(str[l], str[r])) { res += 2; if(res > maxn) { maxn = res;L = l,R = r; } }else break; l = FindLeft(l, 1); r = FindRight(r , 1); } res = 0; l = FindLeft(pos - 1, 0); r = FindRight(pos, 0); while (true) { //偶数 左侧开始双向发散 if(l == -1 || r == -1)break; if(judge(str[l], str[r])) { res += 2; if(res > maxn) { maxn = res; L = l,R = r; } } else break; l = FindLeft(l, 1); r = FindRight(r, 1); } res = 0; l = FindLeft(pos, 0); r = FindRight(pos + 1, 0); while (true) { // printf("l == %d r == %d\n",l,r); if(l == -1 || r == -1)break; if(judge(str[l], str[r])) { res += 2; if(res > maxn) { maxn = res; L = l, R = r; } } else break; l = FindLeft(l, 1); r = FindRight(r, 1); }}int main(){ int t; scanf("%d",&t); getchar(); while ( t -- ) { gets(str); maxn = 0; length = strlen(str); for (int i = 0; i < length ; i ++) lps(i); if(maxn == 0) { for (int i = 0; i < length; i ++) { if(isalpha(str[i])) { L = R = i;break; } } } // printf("%d \n",maxn); for (int i = L; i <= R; i ++) printf("%c",str[i]); printf("\n"); }}
如果你觉得上一份代码 冗长不想看 这里有一份 来自NYOJ的代码
思路和我上面的这个很像 但是写的比我更短更清晰更睿智
有些人总是能写得很简洁 很高效
#include<iostream>#include<string.h>#include<ctype.h>#include<cstdio>using namespace std;const int MAX=5100;char Yuan[MAX],s[MAX];int p[MAX];int main(){/*freopen("1.txt","r",stdin);freopen("2.txt","w",stdout);*/int n;cin>>n;getchar();while(n--){int max=0,x,y,m=0;gets(Yuan);int n=strlen(Yuan);for(int i=0;i<n;i++){if(isalpha(Yuan[i])){p[m]=i;s[m++]=toupper(Yuan[i]);}}for(int i=0;i<m;i++){for(int j=0;i-j>=0&&i+j<m;j++){if(s[i-j]!=s[i+j])break;if(j*2+1>max){max=j*2+1;x=p[i-j];y=p[i+j];}}for(int j=0;i-j>=0&&i+j+1<m;j++){if(s[i-j]!=s[i+j+1])break;if(j*2+2>max){max=j*2+2;x=p[i-j];y=p[i+j+1];}}}for(int k=x;k<=y;k++){printf("%c",Yuan[k]);}cout<<endl;}}
第二种方法
写法比较简单 思路是这样的 暴力枚举所有区间 在暴力匹配区间是不是回文区间 维护最大值 即可
这种方法 复杂度 n^3 浪费时间在检测一个区间是不是回文区间上
因为这种方法没有任何地方比上面给的方法好 就不写了
当然你可以用马拉车算法优化判断回文的过程 这样就比上面的代码快了 但是由于上一份代码 0ms 就没有去学马拉车写法的动力了
留着以后补上吧还是
阅读全文
0 0
- NSWOJ 1228 && NYOJ 132 最长回文子串
- nyoj-132-最长回文子串
- nyoj 132-最长回文子串
- nyoj 132 最长回文子串
- NYOJ - 最长回文子串
- NYOJ-132-最长回文子串-2013年08月12日21:49:03
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- HDOJ 1003 MaxSum(动态规划 求最大子序列和)
- [书单 makefile视频]
- 时间同步
- PTA甲 1003. Emergency (25)
- 标注那点事
- NSWOJ 1228 && NYOJ 132 最长回文子串
- spring boot + quartz实现定时程序调度
- mysql高级笔记(一)
- 题目1019:简单计算器
- 最小均方(LMS)算法
- 移远 BC95 海思 NBIOT 物联网模块 规格 手册 说明
- 进程与线程
- Spring 4.0 学习日记(5) ---bean的自动装配
- C# Session操作类