标签:hid i+1 close bre std out names lse 题解
题意如下:给你一个字符串s,给出q次询问,要你求出区间【l,r】中回文子串的数目!
首先的想法是预处理好在一段区间内的的子串是不是回文子串,这可以通过o(n^2)时间内预处理好!
然后接下来是转移方程,我一开始就往n^3的算法去想,发现超市,后来又发现这样无法转移!
后来看了别人的题解才想到递推方程是dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+hw[i][j],为什么要这样转移呢,原理很简单,这样可以避开判断中间的回文串,但是我一直在中间想,没往边界想,哎。还是太年轻啊。。。。。。。。。。。。。。。。。。。。。。。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 char sz[5100]; 4 int q,len,l,r,n; 5 int hw[5100][5100]; 6 int dp[5100][5100]; 7 int main(){ 8 scanf("%s",sz+1); 9 len=strlen(sz+1); 10 n=len; 11 for(int i=1;i<=len;i++){ 12 for(int j=1;j<=len;j++){ 13 if(i-j<=0||i+j>len) break; 14 if(sz[i-j]==sz[i+j]) hw[i-j][i+j]=1; 15 else break; 16 } 17 for(int j=1;j<=len;j++){ 18 if(i-j+1<=0&&i+j>len) break; 19 if(sz[i-j+1]==sz[i+j]) hw[i-j+1][i+j]=1; 20 else break; 21 } 22 } 23 scanf("%d",&q); 24 for(int i=1;i<=n;i++) dp[i][i]=1; 25 for(int i=2;i<=n;i++){ 26 for(int j=1;j<=n;j++){ 27 if(i+j-1>n) break; 28 int p=i+j-1; 29 dp[j][p]=dp[j][p-1]+dp[j+1][p]-dp[j+1][p-1]+hw[j][p]; 30 } 31 } 32 while(q--){ 33 scanf("%d%d",&l,&r); 34 cout<<dp[l][r]<<endl; 35 } 36 return 0; 37 }
标签:hid i+1 close bre std out names lse 题解
原文地址:https://www.cnblogs.com/pandaking/p/9973118.html