这道题卡了三天啊……暴力超时, 后缀树组咱不会, 于是我上NOCOW看解题报告, 发现一个所谓的DP
//dp[i]代表以sr[i]结尾的最长回文的长度;
if( str[i]==str[i-1-dp[i-1]]) dp[i]=dp[i-1]+2;// else if( str[i]==str[i-1]) dp[i]=2; else dp[i]=1;这个显然不对, 如果str[i]与str[i-1-dp[i-1]] 不相等的话,str[i]可能与i-1-dp[i-1]到i中的任何一个相等,并构成回文;因此不一定对;
还有一种DP
// 下面有一个简单的算法实现流程 令b[i][j]表示是否存在恰好以i个字符尾长度为j的回文串(其中 0<=j<=i) f[i]表示是恰好以第i个字符结尾的回文串最大长度 //令b初始化为flase; b[1][0]=true; b[1][1]=true; f[1]=1; for(int i=2;i<len;i++) { f[i]=-1; b[i][0]=true; for(j=i-1;j>=0;j--) if(b[i-1][j]) { if(i-j-1>0 && a[i]==a[i-j-1]) { b[i][j+2]=true; if (j+2>f[i]) f[i]=j+2; } } }我试了下, 在URAl上1297根本过不了……
昨天学了个求最长回文的manacher算法, O(n)的时间复杂度, 和o(n)的空间复杂度;
今天写了下, 果断AC了……而且秒过……
/* ID:AC_man LANG:C++ TASK:calfflac */ /* USER: AC man [ac_man1] TASK: calfflac LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 3364 KB] Test 2: TEST OK [0.000 secs, 3368 KB] Test 3: TEST OK [0.000 secs, 3364 KB] Test 4: TEST OK [0.000 secs, 3364 KB] Test 5: TEST OK [0.000 secs, 3368 KB] Test 6: TEST OK [0.000 secs, 3368 KB] Test 7: TEST OK [0.000 secs, 3368 KB] Test 8: TEST OK [0.000 secs, 3368 KB] All tests OK. */ #include<iostream> #include<cstring> #include<fstream> using namespace std; int main() { ifstream fin("calfflac.in"); ofstream fout("calfflac.out"); char str[20001], str1[20001], str2[40005]; int num[20001]; int i, j; i=0;j=0; while (!fin.eof()) { str[i]=fin.get();//从文件中获取字符 //如果为字母,就转化为大写存入str1中;num[j]=i表示str1中第j个字母对应于str中第i个字符 if( str[i]>='A'&&str[i]<='Z' || str[i]>='a'&&str[i]<='z' ) { str1[j]=str[i]; if( str1[j]>='a'&&str1[j]<='z' ) str1[j]-=32; num[j]=i; j++; } i++; } //manacher算法 str2[0]=str2[1]='#'; j=2; for(i=0; str1[i]!='\0'; i++) { str2[j++]=str1[i]; str2[j++]='#'; } str2[j]='\0'; int maxx=0, p[40005], mx=0, id=0, record, record1; for(i=1; str2[i]!='\0'; i++) { if( mx>i ) p[i]=min(p[2*id-i], mx-i); else p[i]=1; while( str2[i-p[i]]==str2[i+p[i]]) p[i]++; if(i+p[i]>mx ) { mx=i+p[i]; id=i; } if( p[i]-1>maxx ) { maxx=p[i]-1; record=(i-maxx)/2;//记录对应于str1的下标; str1中回文的起始 record1=(i+maxx)/2-1; //str1中回文的最后 } } fout<<maxx<<endl; int s=num[record], e=num[record1];// for(i=s; i<=e; i++) fout<<str[i]; fout<<endl; }