首页 > 技术文章 > 回文密码

war1111 2017-08-15 10:57 原文

T2.回文密码password.cpp/pas/in/out

时间限制:1s

空间限制:256MB

  伊利斯.逐星:多亏了你的相助,我们通过了第一层。那些蜘蛛真是另令人作呕。现在,我们来到了城堡二层,但是……恐怕又要麻烦你了。

  布莱恩.铜须:你猜猜我们看到了什么?乌瑟尔!我的好朋友,他的尸体就这么被克尔苏加德转化成为了亡灵!还被冻在冰块里!我一定要找到这个可恶的死灵法师,把他砸成肉饼!

  芬利.莫格顿:%^&##@#%^

  (旁边还有克尔苏加德留给我们的谜题!上面写着……)

  雷诺.杰克逊:糟了!我们必须在一秒内解开密码,否则……乌瑟尔将会从冰雕里……解放出来……将我们杀掉。

题目描述:

他们又遇到麻烦了,现在需要你帮助他们解开克尔苏加德的密码。

有这样一串数字和若干次询问,对于每次询问,求出该询问区间的最长回文子串长度,所有的结果的组合就是通往下一层的密码

数据输入:

第一行n表示数字串长度,第二行一串长度为n的数字串(数字范围0~9)。第三行m表示询问的次数,第4~4+m-1行每行一组LiRi表示询问区间。

数据输出:

m行,每行对应一个询问。

输入样例:

  10

  1 2 3 4 5 5 4 3 2 1

  2

  1 10

  2 9

输出样例:

  10

8

数据范围:

0<n<=100000,0<m<=1000000|Ri-Li|<=20

30%n,m<=200;

30%~60%,n,m<=2000;

 

2014级学长老爷子(冯俊杰)出的题,质量还是相当高的,是一个dpf[i][j]表示从i开始长度为j的序列中最长的回文序列的长度,转移方程为

if(f[i+1][j-2]==j-2&&a[i]==a[i+j-1])

       f[i][j]=j;

     else

  f[i][j]=max(f[i+1][j-1],f[i][j-1]);

长度是外循环。

#include<bits/stdc++.h>
using namespace std;

int n,m;
int a[201000];
int f[201000][210];

void in(int &x)
{
    char c=getchar();x=0;
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
}

void out(int x)
{
    if(x>9) out(x/10);
    putchar(x%10+'0');
}

int main()
{
    
  freopen("password.in","r",stdin);
  freopen("password.out","w",stdout);
  cin>>n;
  for(int i=1;i<=n;i++)
      in(a[i]);
  for(int i=1;i<=n;i++)
      f[i][1]=1;
      
 for(int j=2;j<=n&&j<=200;j++)
  for(int i=1;i+j-1<=n;i++)
    {
        if(f[i+1][j-2]==j-2&&a[i]==a[i+j-1])
          f[i][j]=j;
        else
          f[i][j]=max(f[i+1][j-1],f[i][j-1]);
    }
    in(m);
    int x,y;
    for(int i=1;i<=m;i++)
      {
          in(x),in(y);
          out(f[x][y-x+1]);
          putchar('\n');
      }
  return 0;
}

 

推荐阅读