动态规划
如果给定一个区间,i,j 字符串如果a[i] == a[j] ,那么就判断a[i+i] 与a[j-1]是否相等一直到偶数或者奇数形式,判断这个字符串是不是回文字符串。
状态:dp[i][j] 表示字符串s在[i,j]区间的子串是否是一个回文串。
状态转移方程:当 s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1]) 时,dp[i][j]=true,否则为false
class Solution {
public int countSubstrings(String s) {
//有一个二维的boolean类型的数组来进行判断
boolean[][] flag = new boolean[s.length()][s.length()];
int ans =0;
for(int i = 0;i<s.length();++i){
for(int j = 0;j<=i;++j){
if(s.charAt(j) == s.charAt(i) && ((i-j<2) || flag[j+1][i-1] == true)){
flag[j][i] = true;
ans++;
}
}
}
return ans;
}
}
要注意,i是大的数在右边,所以判断的时候是i-j,j是小的数,在左边。
中心扩展法
这是一个比较巧妙的方法,实质的思路和动态规划的思路类似。
比如对一个字符串ababa,选择最中间的a作为中心点,往两边扩散,第一次扩散发现left指向的是b,right指向的也是b,所以是回文串,继续扩散,同理ababa也是回文串。
这个是确定了一个中心点后的寻找的路径,然后我们只要寻找到所有的中心点,问题就解决了。
中心点一共有多少个呢?看起来像是和字符串长度相等,但你会发现,如果是这样,上面的例子永远也搜不到abab,想象一下单个字符的哪个中心点扩展可以得到这个子串?似乎不可能。所以中心点不能只有单个字符构成,还要包括两个字符,比如上面这个子串abab,就可以有中心点ba扩展一次得到,所以最终的中心点由2 * len - 1个,分别是len个单字符和len - 1个双字符。
a b a 中心点就有 aba 三个字符 以及 ab 和 ba之间的空隙
偶数同此
举个例子
假如是abcedf
center的取值范围为0 ~12-1
right与left的指向就是中心点
可能指向同一个点,那么该点第一次判断一定是true,加入都指向b,ans++,下一步left指向a right指向b,这样不等于之后就跳出循环。
同理可知,right与left不指向同一个节点,可能指向前后两个节点ce,这种
class Solution {
public int countSubstrings(String s) {
int ans = 0;
for(int center = 0;center<s.length()*2 -1 ;++center){
int left = center/2;
int right = left+center%2;
while(left>=0 && right<s.length()&& s.charAt(left) == s.charAt(right)){
left--;
right++;
ans++;
}
}
return ans;
}
}