回文密碼
T2.回文密碼(password.cpp/pas/in/out)
時間限制:1s
空間限制:256MB
伊利斯.逐星:多虧了你的相助,我們通過了第一層。那些蜘蛛真是另令人作嘔。現在,我們來到了城堡二層,但是……恐怕又要麻煩你了。
布萊恩.銅須:你猜猜我們看到了什麽?烏瑟爾!我的好朋友,他的屍體就這麽被克爾蘇加德轉化成為了亡靈!還被凍在冰塊裏!我一定要找到這個可惡的死靈法師,把他砸成肉餅!
芬利.莫格頓:%^&##@#%^
(旁邊還有克爾蘇加德留給我們的謎題!上面寫著……)
雷諾.傑克遜:糟了!我們必須在一秒內解開密碼,否則……烏瑟爾將會從冰雕裏……解放出來……將我們殺掉。
題目描述:
他們又遇到麻煩了,現在需要你幫助他們解開克爾蘇加德的密碼。
有這樣一串數字和若幹次詢問,對於每次詢問,求出該詢問區間的最長回文子串長度,所有的結果的組合就是通往下一層的密碼
數據輸入:
第一行n表示數字串長度,第二行一串長度為n的數字串(數字範圍0~9)。第三行m表示詢問的次數,第4~4+m-1行每行一組Li,Ri表示詢問區間。
數據輸出:
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級學長老爺子(馮俊傑)出的題,質量還是相當高的,是一個dp,f[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]; voidin(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; }
回文密碼