您的位置:首页 > 其它

1.3.3 Calf Flac(求最长回文)

2011-12-23 15:52 344 查看
   这道题卡了三天啊……暴力超时, 后缀树组咱不会, 于是我上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;
}












                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 user c