// 区间dp
import java.util.Scanner;/**** @author CN*/
public class main {static int mod = 10007;static String l;static int[][] dp = new int[1010][1010];public static void main(String[] args){// TODO code application logic hereint t;Scanner sc = new Scanner(System.in);t = sc.nextInt();for(int i=1;i<=t;i++){ l = sc.next();for(int p=0;p<1010;p++){for(int q=0;q<1010;q++)dp[p][q] = 0;}for(int r=0;r<l.length();r++)dp[r][r] = 1;for(int len = 1;len<l.length();len++){for(int p=0;p<l.length();p++){for(int q=p+len;q<l.length();q++){dp[p][q] = dp[p+1][q] + dp[p][q-1];if(l.charAt(p)!=l.charAt(q))dp[p][q]-=dp[p+1][q-1];else dp[p][q]++;dp[p][q]=(dp[p][q]+mod)%mod; break;}}}System.out.println("Case "+i+": "+dp[0][l.length()-1]); }}
}
import java.util.Scanner;
// 记忆化搜索写法public class Main {static int mod = 10007;static String l;static int[][] dp = new int[1010][1010];static int dfs(int le,int rt){if(le>rt)return 0;if(le==rt)return 1;if(dp[le][rt]!=-1)return dp[le][rt];dp[le][rt] = (dfs(le+1,rt)+dfs(le,rt-1) - dfs(le+1,rt-1)+ mod)%mod;if(l.charAt(le)==l.charAt(rt))dp[le][rt] = (dfs(le,rt)+dfs(le+1,rt-1)+1)%mod;return dp[le][rt];}public static void main(String[] args){int t;Scanner sc = new Scanner(System.in);t = sc.nextInt();for(int i=1;i<=t;i++){ l = sc.next();for(int p=0;p<l.length();p++){for(int q=0;q<l.length();q++)dp[p][q] = -1;} System.out.println("Case "+i+": "+dfs(0,l.length()-1)); }}
}
题意就是在一个字符串计数任意可能的回文子串 计算所有子串的数量 每个字串要求先后顺序相同
思路:
也就是根据子串的左右边界定义一个子串用dp[i][j]表示从i到j的所有的回文子串的数量
分析可知 dp[i][j] 可以由两个状态转移得来 也就是dp[i+1][j] 和 dp[i][j-1]之和得来
如果i处的字符不等于j处的字符 需要减去一个公共部分dp[i+1][j-1] 因为以上两个状态中的任意一个状态都会包含这个状态的
信息 所以会多一个dp[i+1][j-1] 不妨减去
如果i字符等于j处字符 也就是可以构成一个新的回文子串 这个数量关系 仍然是dp[i-1][j-1]得来
或者使用记忆化搜索去做 一开始可以把所有值初始化为一个不可能值 比如-1如果这个值搜索到的时候非-1 也就是已经搜索过了
可以直接返回
注意有减法的取模操作 +mod 再%mod
一开始Case后面多了个# WA了好几发 。。。坑啊。。。