647. 回文子串-M

647. 回文子串-M

label: dp,回文,面试,经典

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

示例 1:

输入: “abc”
输出: 3
解释: 三个回文子串: “a”, “b”, “c”.

示例 2:

输入: “aaa”
输出: 6
说明: 6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”.

注意:

输入的字符串长度不会超过1000。
在真实的面试中遇到过这道题?

分析:

  1. 暴力,统计s[i,j] i<=j 是回文的个数,O(N ^ 2)
  2. dp, dp[i][j]表示s[i,j]是回文,转移方程dp[i][j]=1 when dp[i+1][j-1]==1 and s[i]==s[j],最后统计dp[i][j]==1的个数;注意这里需要到这是按列走,即更新完dp[x][i]的所有情况,并且都是从1开始,否则容易丢失中间是回文的情况。
  3. 从中心向两边扩,有两种情况,奇数,偶数
package main

import "fmt"

func reverse(s string)string{
	a:=make([]byte,len(s))
	for i:=len(s)-1;i>=0;i--{
		a[len(s)-i-1]=s[i]
	}
	return string(a)
}
//暴力
/*
执行用时 :800 ms, 在所有 Go 提交中击败了5.77%的用户
内存消耗 :10.6 MB, 在所有 Go 提交中击败了11.11%的用户
*/
func countSubstrings_baoli(s string) int {
	count:=0
	for i:=0;i<len(s);i++{
		for j:=i;j<len(s);j++{
			if s[i:j+1]==reverse(s[i:j+1]){
				count+=1
			}
		}
	}
	return count
}
/*
dp: if dp[i+1][j-1]==1&&s[i]==s[j]{dp[i][j]=1},count(dp[i][j]>0)
执行用时 :24 ms, 在所有 Go 提交中击败了25.00%的用户
内存消耗 :17.1 MB, 在所有 Go 提交中击败了11.11%的用户
*/
func countSubstrings_dp(s string) int {
	dp:=make([][]int,len(s)+1)
	for i:=0;i<=len(s);i++{
		dp[i]=make([]int,len(s)+1)
	}
	count:=0
	for j:=1;j<=len(s);j++{
		for i:=1;i<=len(s);i++{//dp[x][j]更新完毕,即s[j]之前的都计算好了,
			//往两边看
			if i+1<=j-1&&dp[i+1][j-1]==1&&s[i-1]==s[j-1]{ dp[i][j]=dp[i+1][j-1]}
			//i+2>j
			if i+1>j-1&&s[i-1]==s[j-1]{ dp[i][j]=1 }
		}
	}
	for i:=0;i<=len(s);i++{
		for j:=i;j<=len(s);j++{
			if dp[i][j]>0{
				count+=1
			}
		}
	}
	return count
}
//两边扩
/*
执行用时 :0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗 :2 MB, 在所有 Go 提交中击败了88.89%的用户
*/
func countSubstrings(s string) int {
	ret:=0
	for i:=0;i<len(s);i++{
		ret+=counting(s,i,i)//奇数形式,counting会记录s[i]==s[i]的
		ret+=counting(s,i,i+1)//偶数形式,counting会计算s[i]==s[i+1]的
	}
	return ret
}
func counting(s string ,a,b int)int{
	count:=0
	for a>=0&&b<len(s)&&a<=b&&s[a]==s[b]{
		count+=1;a-=1;b+=1
	}
	return count
}
func main() {
	tables:=[]string{
		"abc",
		"aaa",
		"abbaccbb", //12
	}
	for _,v:=range tables{
		fmt.Println(countSubstrings_baoli(v))
		fmt.Println(countSubstrings(v))
	}
}

你可能感兴趣的:(647. 回文子串-M)