dp我突然觉得 没必要将它仔细地分成各种种类 都是利用了差不多什么递推 利用前面计算出来的子结果什么的思想
这题的状态 不难想 因为一个回文串肯定是有左右端点啊 那么就肯定有2维状态了 然后就是递推吧
这边有些初始化 可以先完成 也可以在解决的时候 一并完成 随你
我一开始自己写的是 记忆化搜索的写法. 然后有人写了直接for递推的 速度比我这 递归的快了3倍吧
我把2种都贴上来 顺便写下 状态转移方程
dp[x][y] = dp[x][y-1] + dp[x+1][y] - dp[x+1][y-1] if str[x]==str[y] dp[x][y] += dp[x+1][y-1] + 1;
1 #include2 #include 3 using namespace std; 4 5 const int size = 1010; 6 const int mod = 10007; 7 int len; 8 char str[size]; 9 int dp[size][size];10 11 int dfs( int L , int R )12 {13 if( L<1 || R>len || L>R )14 return 0;15 if( dp[L][R] )16 return dp[L][R];17 if( L==R )18 {19 dp[L][R] = 1;20 }21 else if( L+1==R ) 22 {23 if( str[L]==str[R] )24 {25 dp[L][R] = 3;26 }27 else28 {29 dp[L][R] = 2;30 }31 }32 else33 {34 if( str[L] == str[R] )35 dp[L][R] = ( dfs( L , R-1 ) + dfs( L+1 , R ) + 1 ) % mod ;36 else37 dp[L][R] = ( dfs( L , R-1 ) + dfs( L+1 , R ) - dfs( L+1 , R-1 ) + mod ) %mod;38 }39 return dp[L][R];40 }41 42 int main()43 {44 int t , ans;45 scanf("%d",&t);46 for( int k = 1 ; k<=t ; k++ )47 {48 cin >> (str+1);49 len = strlen(str+1);50 memset( dp , 0 , sizeof(dp) );51 ans = dfs( 1 , len );52 printf("Case %d: %d\n",k,ans%mod);53 }54 return 0;55 }
那个for循环的外层是区间长度 内存是左边端点起始坐标 这个递推顺序一定不能错 你可以根据你的状态转移方程来确定
1 #include2 #include 3 using namespace std; 4 5 const int size = 1010; 6 const int mod = 10007; 7 int len; 8 char str[size]; 9 int dp[size][size];10 11 void solve( )12 {13 for( int i = 1 ; i<=len ; i++ )14 {15 for( int j = 1 ; j+i<=len ; j++ ) 16 {17 if( str[j] == str[i+j] )18 dp[j][i+j] = dp[j+1][i+j] + dp[j][i+j-1] + 1;19 else20 dp[j][i+j] = dp[j+1][i+j] + dp[j][i+j-1] - dp[j+1][i+j-1];21 dp[j][i+j] = (dp[j][i+j]+mod)%mod;22 }23 }24 }25 26 int main()27 {28 int t , ans;29 scanf("%d",&t);30 for( int k = 1 ; k<=t ; k++ )31 {32 cin >> (str+1);33 len = strlen(str+1);34 memset( dp , 0 , sizeof(dp) );35 for( int i = 1 ; i<=len ; i++ )36 dp[i][i] = 1;37 solve( );38 printf("Case %d: %d\n",k,dp[1][len]%mod);39 }40 return 0;41 }
today:
11.11 童话里都是骗人的