字符串取出部分字符后变为回文字符串(二)

本文介绍了如何通过暴力搜索的方法,从给定字符串中移除字符以形成回文字符串的方案。通过遍历所有可能的子集,判断剩余字符串是否为回文,从而找出所有可能的组合。示例和代码详细解释了这一过程。

这个属于一种暴力搜索的手段。输入牛客网测试区会显示运行超时!

运行通过见我的另一篇构造回文博客。

问题描述:

对于一个字符串,从前开始读和从后开始读是一样的则称为回文字符串。

有一个字符串s,有多少中方案从该字符串中移除0个或多个字符串使其变为回文串。

其中,空串不算字符串。对于两种移除方案,如果移除的字符依次构成的序列不一样就是不同的方案。

示例:XXY 对应 X,XY,YX,Y 4中移除方案。


思路:

1、求出所有字符串的子集;

2、在求子集的过程中:

        a. 每得到一个子集,将子集看作删除的字符串;

        b. 用原字符串减掉上述子集;得到剩下的字符串;

        c. 判断上述剩下的字符串是否为回文字符串;是则将a中子集放入一个无重复元素的List;


整体代码如下(以“XXYYXX”为例):

package ali.example;

import java.util.ArrayList;
import java.util.List;

public class J030409New {
	static public String stry = null;
	
	static public List<String> subStr = new ArrayList<String>();
	static public List<String> delStr = new ArrayList<String>();
	
	public static boolean putInList(List<String> StrList,String s) {
		for(int i = 0; i < StrList.size();i++)
			if(s.equals(StrList.get(i)))
				return false;
		StrList.add(s);
		return true;
	}
	
	
	public static boolean isPalindrome(String src)  
	{  
	    if(src == null || src.equals("")) return false;  
	    int end = src.length()-1,begin = 0;  
	    while(begin < end)//从两边向中间判断,当然也可以从中间向两边判断  
	    {  
	        if(src.charAt(begin) != src.charAt(end))return false;  
	        begin ++;  
	        end --;  
	    }  
	    return true;  
	}
	
	
	//删除src中index位置的元素
	public static String subStringNew(String src,int index)  
	{  
	    if(src.length() == 1)
	    	return "";
	    else
	    	if(index == 0) {
	    		return src.substring(1);}
	    	else if(index == src.length()-1)
	    		return src.substring(0,src.length()-1);
	    	else
	    		return src.substring(0,index)+src.substring(index+1);
	    
	}
	
	
	//从srcIn依次减去其子集srcPa中的字符,而不伤害srcIn
	public static String strsubStr(String srcIn,String srcPa)  
	{  
		String s = new String(srcIn);
		int j = -1;
		char c ;
	    for(int i = 0;i<srcPa.length();i++) {
	    	c = srcPa.charAt(i);
	    	j = s.indexOf(c);
	    	if(j == -1)
	    		{
	    		   System.err.println("srcPa 不是 srcIn的子集");
	    		   System.exit(0);
	    		}
	    	s = subStringNew(s,j);
	    }
	    return s;   
	}
	
	private static List<String> get_Subset(String str) {
		List<String> subStr1 = new ArrayList<String>();
		if(str.equals("")) {
			subStr1.add("");
			putInList(subStr,"");	
			if(isPalindrome(strsubStr(stry,"")))
				putInList(delStr, "");
			return subStr1;
		}
		
		for(int i = 0;i<str.length();i++) {
			String s=subStringNew(str,i);
			List<String> subStr2 = get_Subset(s);
			for(int j = 0;j<subStr2.size();j++) {
				subStr1.add(str.charAt(i)+subStr2.get(j));
				putInList(subStr,str.charAt(i)+subStr2.get(j));
				
				//判断减去此字符串后是否为回文字符串
				if(isPalindrome(strsubStr(stry,str.charAt(i)+subStr2.get(j))))
					putInList(delStr, str.charAt(i)+subStr2.get(j));
			}
		}
		return subStr1;
		
		
	}
	
	public static void main(String[] args) {
        stry = "xxyyxx";
        get_Subset(stry);
        for(int j = 0;j<subStr.size();j++) {
        	 System.out.println(subStr.get(j));
		}
        
        
//        System.out.println(strsubStr("aabbcc","abbc"));
        
    }

}


其中:

求子集:

        a. 空集的子集为空集;

        b. 非空集的子集:对于一个字符串S:依次读取字符串中的字符为作为子集字符串的第一个元素a;求剩余元素的全部子集A;所有的a分别匹配所有的A中元素即为S的全部子集(不含空集);

        c. 求A的过程中,由于A也是S的子集,所以将过程中所有的A存入总的S的不重复子集List;



求子集函数:


private static List<String> get_Subset(String str) {
		List<String> subStr1 = new ArrayList<String>();  //单次子集List
		if(str.equals("")) {
			subStr1.add("");
			putInList(subStr,"");	  //总的子集List,定义为类的static变量
//			if(isPalindrome(strsubStr(stry,"")))
//				putInList(delStr, "");
			return subStr1;
		}
		
		for(int i = 0;i<str.length();i++) {
			String s=subStringNew(str,i);
			List<String> subStr2 = get_Subset(s);
			for(int j = 0;j<subStr2.size();j++) {
				subStr1.add(str.charAt(i)+subStr2.get(j));
				putInList(subStr,str.charAt(i)+subStr2.get(j));
				
				//判断减去此字符串后是否为回文字符串
//				if(isPalindrome(strsubStr(stry,str.charAt(i)+subStr2.get(j))))
//					putInList(delStr, str.charAt(i)+subStr2.get(j));
			}
		}
		return subStr1;
		
		
	}


从字符串src中删去index处的字符:注意String.substring(begin,end)不包含end处元素;String.substring(begin)表示从begin取到尾

//删除src中index位置的元素
	public static String subStringNew(String src,int index)  
	{  
	    if(src.length() == 1)
	    	return "";
	    else
	    	if(index == 0) {
	    		return src.substring(1);}
	    	else if(index == src.length()-1)
	    		return src.substring(0,src.length()-1);
	    	else
	    		return src.substring(0,index)+src.substring(index+1);
	    
	}

从字符串srcIn依次减去其子集srcPa,而不伤害srcIn

        a. 依次读取srcPa的字符c;

        b. 删除srcIn首次出现的c;

字符串减子字符串函数:

//从srcIn依次减去其子集srcPa中的字符,而不伤害srcIn
	public static String strsubStr(String srcIn,String srcPa)  
	{  
		String s = new String(srcIn);
		int j = -1;
		char c ;
	    for(int i = 0;i<srcPa.length();i++) {
	    	c = srcPa.charAt(i);
	    	j = s.indexOf(c);
	    	if(j == -1)
	    		{
	    		   System.err.println("srcPa 不是 srcIn的子集");
	    		   System.exit(0);
	    		}
	    	s = subStringNew(s,j);
	    }
	    return s;   
	}


字符串放入不重复List:放入时遍历List以确认没有该元素的存在。注意Object.equal()的使用

public static boolean putInList(List<String> StrList,String s) {
		for(int i = 0; i < StrList.size();i++)
			if(s.equals(StrList.get(i)))
				return false;
		StrList.add(s);
		return true;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值