题意:原题在这
You‘ve got a string s = s1s2... s|s| of length |s|, consisting of lowercase English letters. There also are q queries, each query is described by two integers li, ri (1 ≤ li ≤ ri ≤ |s|). The answer to the query is the number of substrings of string s[li... ri], which are palindromes.
String s[l... r] = slsl + 1... sr (1 ≤ l ≤ r ≤ |s|) is a substring of string s = s1s2... s|s|.
String t is called a palindrome, if it reads the same from left to right and from right to left. Formally, if t = t1t2... t|t| = t|t|t|t| - 1... t1.
给定一个字符串,q个询问,每个询问这个区间内有多少个回文串
思路:
定义vis[i][j]表示是不是回文串;
dp[i][j]为i到j的回文串总数
初始化一个:
1.自己是回文串
2.相邻的是回文串
再用can(x,y)递归判断vis[x][y]其他情况:
bool can(int x,int y) { if (vis[x][y]) return true; else return vis[x][y]=(s[x]==s[y])&&(can(x+1,y-1)); }
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define inf 99999999999 #define maxn 1000005 using namespace std; string s; int q,cnt,len; bool vis[5005][5005];//vis[i][j]表示是否为回文串 int dp[5005][5005];//dp[i][j]表示回文子串数量 struct description { int l,r; }f[maxn]; bool can(int x,int y) { if (vis[x][y]) return true; else return vis[x][y]=(s[x]==s[y])&&(can(x+1,y-1)); } int main() { cin>>s; len=s.size(); //初始化 memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); for(int i=0;i<=len;i++)//自己是回文串 { vis[i][i]=1; dp[i][i]=1; } for(int i=0;i<len;i++)//相邻的也是 { if(s[i]==s[i+1]) { vis[i][i+1]=1; dp[i][i+1]=3; } else dp[i][i+1]=2; } for(int k=2;k<len;k++) { int l=0; for(int r=k;r<len;r++) { dp[l][r]=dp[l+1][r]+dp[l][r-1]-dp[l+1][r-1]; if (can(l,r)) dp[l][r]++; l++; } } cin>>q; for(int i=1;i<=q;i++) { scanf("%d%d",&f[i].l,&f[i].r); // cin>>f[i].l>>f[i].r; // cout<<dp[f[i].l-1][f[i].r-1]<<endl; printf("%d\n",dp[f[i].l-1][f[i].r-1]); } return 0; }
原文地址:https://www.cnblogs.com/LocaEtric/p/9615062.html
时间: 2024-10-18 17:27:10