1.3.3 Calf Flac(求最长回文)

   这道题卡了三天啊……暴力超时, 后缀树组咱不会, 于是我上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=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
#include
#include
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<


 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(DP,USACO)