時間限制:2000ms
單點時限:1000ms
記憶體限制:256mb
描述 給定字串,求它的回文子串行個數。回文子串行反轉字元順序後仍然與原序列相同。例如字串aba中,回文子串行為」a」, 「a」, 「aa」, 「b」, 「aba」,共5個。內容相同位置不同的子串行算不同的子串行。
輸入 第一行乙個整數t,表示資料組數。之後是t組資料,每組資料為一行字串。
輸出 對於每組資料輸出一行,格式為」case #x: y」,x代表資料編號(從1開始),y為答案。答案對100007取模。
資料範圍
1 ≤ t ≤ 30
小資料字串長度 ≤ 25
大資料字串長度 ≤ 1000
樣例輸入
5 aba
abcbaddabcba
12111112351121
ccccccc
fdadfa
樣例輸出
case #1: 5
case #2: 277
case #3: 1333
case #4: 127
case #5: 17
區間dp問題 = =
dp[i][j] 代表i到j區間內的回文子串數量。
那麼它的**有兩個。乙個是 dp[i+1][j] 和 dp[i][j-1];
這裡注意的地方是 , dp[i+1][j] 和 dp[i][j-1]都重複的包含了dp[i+1][j-1];這個區間的字串。所以要減去乙個。
最後注意的地方是 如果 s[i]==s[j]的時候。
那麼dp[i][j]要再加上dp[i+1][j-1]+1;
因為這個時候。i和j 這兩個地方的字元。在和區間i+1到j-1的回文字串中,首先獲得這麼多組合,之後又新增了乙個組合。
因為dp[i+1][j] 和 dp[i][j-1]並沒有包含dp[i+1][j-1]和s[i],s[j],組合的新回文串。
因為懶得想迴圈,直接遞迴操作了- -;
因為發現寫帶返回值的遞迴- - 需要記憶化。和用乙個dp記錄沒什麼區別,直接寫dp了。
我們如果想知道1, 6區間的回文字串,那麼首先要知道 i+1,j和 i,j-1 這兩個區間的東西。
也就是 2 6 和1 5;
這個時候 繼續遞迴下去,
如果想知道2 6 要先知道 3 6 和 2 5 ;
然後繼續下去 。
#pragma comment(linker, "/stack:1024000000,1024000000")
#include
using
namespace
std;
string a;
const
int mod=1e5+7;
int dp[1005][1005];
void dfs(int l,int r)
if(!dp[l+1][r]) dfs(l+1,r);//這兩步屬於記憶化,不算重複的- -。
if(!dp[l][r-1]) dfs(l,r-1);
dp[l][r]=(dp[l+1][r]+dp[l][r-1]-dp[l+1][r-1]+mod)%mod;
if(a[l]==a[r]) dp[l][r]=(dp[l][r]+dp[l+1][r-1]+1)%mod;
}int main()
}}
寫dp的迴圈也很重要。
要確定迴圈的方式。這時候需要乙個完美的邏輯。完美的邏輯不是猜出來的。
對於這個題 是遞迴的思考方式,推理出來的。
#include
using
namespace
std;
int dp[1005][1005];
const
int mod=1e5+7;
int main()}}
cout
<<"case #"
<": "
<0][l-1]<}
}
程式設計之美 回文字元序列
時間限制 2000ms 單點時限 1000ms 記憶體限制 256mb 給定字串,求它的回文子串行個數。回文子串行反轉字元順序後仍然與原序列相同。例如字串aba中,回文子串行為 a a aa b aba 共5個。內容相同位置不同的子串行算不同的子串行。第一行乙個整數t,表示資料組數。之後是t組資料,...
基於棧的回文字元序列判斷
include define maxsize 10000 includeusing namespace std typedef struct sqstack int initstack sqstack s int push sqstack s,char e if s.top s.base s.sta...
基於棧的回文字元序列判斷
描述 回文序列是正反讀均相同的字串行,如 abba 和 abdba 均是回文,但是 good 不是回文。請設計乙個演算法判定給定的字串行是否為回文。輸入多組資料,每組資料有一行。每一行為乙個長度不定的字串行a。當a為 0 時,輸入結束。輸出對於每組資料輸出一行。若字串行a是回文序列,則輸出 yes ...