一道递归问题

题目大意是:给定一个字符串A,然后给定多个单词,然后根据给定的单词在字符串中插入空格,求插入空格最少的组合。例如给定字符串ilikeeverything,给定单词i、like、every、thing、likeeverything。输出为i likeeverything。

#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include<algorithm>
#include<functional>
using namespace std;

string result;
int mincount=1000;
int count1 = 0;
bool flag = false;

//注意递归里面最好不要有全局变量,如果返回,注意保存有上次的值。如果想把本次的值传递到下一次递归,
//完全可以利用参数传值传递,而且返回后,值不变(变化的注意复原)。(我只是在结束条件满足时获得值即可,中间的值我又不需知道)
//local:当前查找的起始位置
//resulttemp:暂存结果,因为会有多个解。
//blanknum:插入的空格数量
//str:要插入空格的字符串
//dict:字典(放入的是多个字符串)
void mincut(int local,string resulttemp,int blanknum,const string& str, const set<string>& dict)
{
	//从起点开始子串依次增长
	for (int i = 1; i <= str.size()-local; i++)
	{
		string strtemp = str.substr(local, i);
		if (dict.find(strtemp) != dict.end())//找到
		{
			//先保存找到的子串
			resulttemp += strtemp;
			resulttemp += ' ';
			blanknum++;
			local = local + i;
			if (local >= str.size())//判断此次是否符合结束条件,符合就接收最后的解
			{
				if (blanknum < mincount)//判断是否是更好的解
				{
					flag = true;//只要有一个解,最终就会有解
					mincount = blanknum;
					result = resulttemp;
				//	cout << result << endl;
				}
			}
			else//不符合结束条件,就继续
			{
				mincut(local, resulttemp, blanknum, str, dict);
				local = local - i;//复原,开始下次循环,注意。
				blanknum--;
				resulttemp.erase(local, resulttemp.size() - local);
			}
		}
	}
}

int main(int argc, const char * argv[])
{
	string strS="aababa";
	set<string> dict;
	result.clear();

	dict.insert("a");
	dict.insert("aa");
	dict.insert("aaa");
	dict.insert("b");
	string resulttemp;
	int blanknum = 0;
	mincut(0, resulttemp, blanknum, strS, dict);
	if (flag)
		cout << result << endl;
	else
		cout << "不存在" << endl;
	system("pause");
	return 0;
}

注意递归的结束条件,本题使用的方法相当于深度优先搜索,一次查找结束的条件是下次查找的起始位置超出字符串的个数。

特别注意递归后的代码如何写(想下递归返回后自己想要干什么,对于本题我的解法相当于深度优先搜索,所以递归返回后会走另一条路,所以还原一些需要用到的变量)


另一道题是:给定一个字符串A,另外给一个字符串B,问A能组合出多少个B?(A中相对顺序要一致)

例:A:asdad  B:asd 输出结果为2

#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include<algorithm>
#include<functional>
using namespace std;
int numcount = 0;
void mincut(int strlocal,int dictlocal, const string str, const string dict)
{
	if (dictlocal == dict.size())
	{
		numcount++;
		return;
	}
	if (strlocal == str.size())
		return;
	for (int i = strlocal; i < str.size(); i++)
	{
		if (str[i] == dict[dictlocal])//找到一个
		{
			mincut(i+1, dictlocal+1, str, dict);
		}
	}
}

int main(int argc, const char * argv[])
{
	string strS;
	string dict;
	while (cin>>strS>>dict)
	{
		numcount = 0;
		mincut(0, 0, strS, dict);
		cout << numcount << endl;
	}
	system("pause");
	return 0;
}
此程序修改的最上面的代码,最上面的代码可以照着下面的修改下,传入变量类似这样写
mincut(i+1, dictlocal+1, str, dict),这样就不用还原i及dictlocal了。

猜你喜欢

转载自blog.csdn.net/E_ROAD_BY_U/article/details/77688350