JAVA程序设计:回文子串(LeetCode:647)

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

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

示例 1:

输入: "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c".
示例 2:

输入: "aaa"
输出: 6
说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
注意:

输入的字符串长度不会超过1000。

方法一:暴力,枚举回文串的中心店即可。复杂度O(n^2)

class Solution {
    public int countSubstrings(String s) {
        
    	int n=s.length();
    	int ans=n;
    	
    	for(int i=1;i<n;i++) {
    		ans+=find(s,i-1,i+1,n);
    		if(s.charAt(i-1)==s.charAt(i))
    			ans+=find(s,i-1,i,n);
    	}
    	
    	return ans;
    }
    
    private int find(String s,int l,int r,int n) {
    	int res=0;
    	while(l>=0 && r<n && s.charAt(l)==s.charAt(r)) {
    		res++;
    		l--;r++;
    	}	
    	return res;
    }
}

方法二:马拉车算法,不懂马拉车的可以看我马拉车讲解文章,相信大家肯定能看懂的。复杂度O(n)

class Solution {
    public int countSubstrings(String s) {
        
    	char[] c=new char[2*s.length()+3];
    	c[0]='@'; c[1]='#'; c[c.length-1]='$';
    	int t=2;
    	for(char cc : s.toCharArray()) {
    		c[t++]=cc;
    		c[t++]='#';
    	}
    	
    	int[] len=new int[c.length];
    	int center=0,right=0;
    	for(int i=1;i<len.length-1;i++) {
    		if(i<right)
    			len[i]=Math.min(right-i, len[2*center-i]);
    		while(c[i+len[i]+1]==c[i-len[i]-1])
    			len[i]++;
    		if(i+len[i]>right) {
    			center=i;
    			right=i+len[i];
    		}
    	}
    	int ans=0;
    	for(int v : len)
    		ans+=(v+1)/2;
    	return ans;
    }
}
发布了987 篇原创文章 · 获赞 175 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/haut_ykc/article/details/104000902