hdu 3068 最长回文子串 TLE

后缀数组+RMQ是O(nlogn)的,会TLE.....

标准解法好像是马拉车,O(n)....

  1 #include "algorithm"
  2 #include "cstdio"
  3 #include "cstring"
  4 using namespace std;
  5 #define maxn 220020
  6
  7 int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
  8 int rank[maxn],height[maxn];
  9 int r[maxn],sa[maxn],RMQ[maxn][20];
 10 char s[110010];
 11 int n;
 12
 13 int cmp(int *r,int a,int b,int l)
 14 {
 15     return r[a]==r[b]&&r[a+l]==r[b+l];
 16 }
 17
 18 void da(int *r,int *sa,int n,int m)
 19 {
 20     int i,j,p,*x=wa,*y=wb,*t;
 21     for(i=0; i<m; i++) ws[i]=0;     //注意此处有个小问题:ws和iostream里面某地重名了..
 22     for(i=0; i<n; i++) ws[x[i]=r[i]]++;
 23     for(i=1; i<m; i++) ws[i]+=ws[i-1];
 24     for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
 25     for(j=1,p=1; p<n; j*=2,m=p)
 26     {
 27
 28         for(p=0,i=n-j; i<n; i++) y[p++]=i;
 29         for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
 30         for(i=0; i<n; i++) wv[i]=x[y[i]];
 31         for(i=0; i<m; i++) ws[i]=0;
 32         for(i=0; i<n; i++) ws[wv[i]]++;
 33         for(i=1; i<m; i++) ws[i]+=ws[i-1];
 34         for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
 35         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
 36             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 37     }
 38     return;
 39 }
 40
 41 void calheight(int *r,int *sa,int n)
 42 {
 43     int i,j,k=0;
 44     for(i=1; i<=n; i++) rank[sa[i]]=i;
 45     for(i=0; i<n; height[rank[i++]]=k)
 46         for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
 47     return;
 48 }
 49
 50 bool _same(int lx,int ly,int l1,int l2)
 51 {
 52     return (((lx<=l1-1) && (ly>=l1+1))||((ly<=l1-1) && (lx>=l1+1)));
 53 }
 54
 55 void ST()        //初始化
 56 {
 57     memset(RMQ,1,sizeof(RMQ));
 58     for(int i=1;i<=n;i++)
 59         RMQ[i][0]=height[i];
 60     for(int j=1;(1<<j)<=n;j++)
 61         for(int i=1;i+(1<<j)-1<=n;i++)
 62         RMQ[i][j]=min(RMQ[i][j-1],RMQ[i+(1<<(j-1))][j-1]);
 63 }
 64
 65 int Query(int L,int R)    //求a[L..R]区间的最值
 66 {
 67     int k=0;
 68     while((1<<(k+1))<=R-L+1) k++;
 69     int tb=min(RMQ[L][k],RMQ[R-(1<<k)+1][k]);
 70     return tb;
 71 }
 72
 73 int calc(int l,int r)       //求l开始后缀和r开始后缀的最长公共前缀
 74 {
 75     int tl=rank[l],tr=rank[r];
 76     if (tl>tr)      swap(tl,tr);
 77     tl++;
 78     int ans=Query(tl,tr);       //相当于RMQ问题
 79 //  printf("calc:  %d %d -- %d %d == %d\n",l,r,tl,tr,ans);
 80     return ans;
 81 }
 82
 83 int _max(int a,int b,int c,int d)
 84 {
 85     int mx=a;
 86     if (b>mx) mx=b;
 87     if (c>mx) mx=c;
 88     if (d>mx) mx=d;
 89     return mx;
 90 }
 91
 92 //da(r,sa,n+1,128);
 93 //calheight(r,sa,n);
 94 int main()
 95 {
 96     while(~scanf("%s",s))
 97     {
 98         n=strlen(s);
 99
100         for (int i=0; i<n; i++)
101             r[i]=int(s[i])-int(‘a‘)+1;
102
103         r[n]=100;
104         for (int i=n-1; i>=0; i--)
105             r[2*n-i]=int(s[i])-int(‘a‘)+1;
106         r[2*n+1]=0;
107         int n2=n;       n=2*n+1;
108
109 //      for (int i=0; i<=n; i++)      printf("%d ",r[i]);
110 //        printf("\n %d   %d\n",n,n2);
111
112         da(r,sa,n+1,128);
113         calheight(r,sa,n);
114
115 //      for (int i=0; i<=n; i++)
116 //          printf("%d  %d  %d\n",sa[i],height[i],rank[i]);
117 //      printf("\n");
118
119         ST();
120         int ans=1;
121         for (int i=1; i<=n2-2; i++)
122         {
123             int t1=calc(i,n-i)*2;
124             int t2=calc(i+1,n-i)*2+1;
125             int t3=calc(i+1,n-i-1)*2;
126 //          printf("%d %d %d\n",t1,t2,t3);
127             ans=_max(ans,t1,t2,t3);
128         }
129         printf("%d\n",ans);
130     }
131     return 0;
132 }

最近两天有点不在状态....先滚去整理模板吧

时间: 2024-10-06 07:18:42

hdu 3068 最长回文子串 TLE的相关文章

hdu 3068 最长回文子串 马拉车模板

前几天用后缀数组写过一次这题,毫无疑问很感人的TLE了-_-|| 今天偶然发现了马拉车模板,O(N)时间就搞定 reference:http://acm.uestc.edu.cn/bbs/read.php?tid=3258 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 #define N 110010 6 char s[N*2],str[N*

HDU 3068 [最长回文子串]

#include<iostream> #include<string> #include<string.h> #include<algorithm> #define MAX_LEN 310000 using namespace std; int p[MAX_LEN]; int findBMstr(string &str){ int maxx=-1; memset(p,0,sizeof(p)); int mx=0,id=0; for(int i=1;i

hdu 3068 最长回文(manacher&amp;最长回文子串)

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7317    Accepted Submission(s): 2500 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

hdu 5340 最长回文子串变形

http://acm.hdu.edu.cn/showproblem.php?pid=5340 Problem Description Can we divided a given string S into three nonempty palindromes? Input First line contains a single integer T≤20 which denotes the number of test cases. For each test case , there is

HDU 3068 最长回文 (manacher算法)

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9188    Accepted Submission(s): 3159 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

HDU 3068(最长回文-manacher)[Template:manacher]

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9660    Accepted Submission(s): 3353 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

HDU - 3068 最长回文(manacher算法)

题意:给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 分析: manacher算法: 1.将字符串中每个字符的两边都插入一个特殊字符.(此操作的目的是,将字符串长度统一变成奇数,道理很容易想---奇数+偶数=奇数or偶数+奇数=奇数) eg:abba--->#a#b#b#a# 此外,为了便于处理边界,可在字符串开始处再加另外一个特殊字符. eg:#a#b#b#a#--->$#a#b#b#a# 2.数组 P[i] 来记录以字符S[i]为中心的最长回文子串向

HDU 3068 最长回文(初遇manacher)

这题可用拓展KMP分治法来做http://blog.sina.cn/dpool/blog/s/blog_677a3eb30100knj8.html 复杂度O(nlogn)这种方法好复杂而且代码很长,不易理解. 相比之下Manacher就简单多了,算法本身也很简单 这里个易懂的资料http://wenku.baidu.com/view/3031d2d3360cba1aa811da42.html 复杂度O(n) kuangbin的模版(有一处修改) /* * 求最长回文子串 */ const int

HDU 3068 最长回文(manacher算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 两组case之间由空行隔开(该空行不用处理) 字符串长度len <= 110000 Output 每