#include<iostream>
#include<math.h>
#include<string.h>
using namespace std;

//奶牛生子:一只幼年奶牛第4年可生下第一只奶牛 以后每年生一只
//现有一只幼年奶牛 20年后 共有多少只奶牛

int CowNum(int size)
{
	int* year = new int[size];
	memset(year, 0, size*sizeof(int));
	year[0] = 1;
	int count = 0;
	for (int i = 0; i < size; ++i)
	{
		if (i >= 4-1 )
		{
			year[i] = year[i - 1] + year[i - 3];
		}
	}
	for (int i = 0; i < size; ++i)
		count += year[i];
	return count;

	delete year;
}

int CowNum1(int year)
{
	int newCow1 = 1;//1岁 牛  开始有1只
	int newCow2 = 0;//2岁 牛
	int newCow3 = 0;//三岁 牛
	int newCow4 = 0;//四岁 牛  成年牛
	//int newCow5 = 0;//将题意理解成第5年牛开始生  则加个5岁牛数量
	int oldCow = 0;//可生崽 牛
	int count = 0; //总数
	for (int yearcnt = 2; yearcnt <= year; ++yearcnt)//默认牛是1岁 第一次进去牛 2岁
	{		
		//newCow5 = newCow4;
		newCow4 = newCow3; //3岁牛长 4岁
		oldCow += newCow4;
		newCow3 = newCow2;
		newCow2 = newCow1;//一岁牛 长2岁
		newCow1 = oldCow;//1岁牛 为可生崽牛 的数量		
		count = oldCow + newCow1+newCow2+newCow3;//总数为 成年牛 + 1 2 3岁牛
		//count = oldCow + newCow1 + newCow2 + newCow3+newCow4; //如果是5岁开始生
		//总数为 成年牛 + 1 2 3 4岁牛
	}
	return count;
}
//一串珠子 有M<=10种颜色 n颗 求最小的含所有颜色的子串
//逻辑复杂的一道题

void AllColorBead(char* bead, int colorNum)//bead 珠子串 colorNum 颜色数
{
	char* head,* str=bead; //head 最短子串头  str 循环变量
	int clrNum = 0 ,beadCnt=0,tmpCnt=1000000,tmpClrNum=-1;
	char colorArr[128] = { 0 };//用来判断每种颜色是否第一次出现 来区分颜色数是否+1
	while (*str!='\0')
	{
		if (*(str + 1) != *str) //如果相连的颜色一样直接跳过
		{
			char* tmp = str; //记录str 如果该子串满足要求 head=str
			while ((*tmp)!='\0')
			{
				
				if (colorArr[*tmp] == 0)//颜色第一次出现 clrNum++
				{
					++clrNum;
					++colorArr[*tmp];
				}
				//if (clrNum == colorNum) //告诉珠子颜色数逻辑
				//{	
				//	if (tmpCnt > beadCnt)//如果该子串满足要求 head = str 跳出循环
				//	{
				//		tmpCnt = beadCnt;
				//		head = str;
				//	}
				//	break;
				//}
				if (tmpClrNum==clrNum)//不告诉珠子颜色数 第一次需完全遍历 求出颜色数
					break;
				
				++beadCnt;
				++tmp;
			}
			if (tmpCnt > beadCnt&&clrNum>=tmpClrNum)//如果该子串满足要求 head = str 跳出循环
			{
				tmpCnt = beadCnt;
				tmpClrNum = clrNum;//不告诉珠子颜色数需加条件
				head = str;
			}
			clrNum = 0; //每次检索子串结束  计数器制零
			beadCnt = 0;
			memset(colorArr, 0, 128 * sizeof(char));
		}
		str++; //×××下一个子串
	}
	for (int i = 0; i <= tmpCnt; ++i)//输出子串
		cout << *(head + i);
	cout << endl;

}

//n*n的 回字形 蛇形 数组 按行输出
// eg: n=3
// 1 2 3
// 8 9 4
// 7 6 5
void SnakeArr(int n)
{
	int* arr = new int[n*n]; //储存数组
	int type = 0;//写入数组类型 0 从左向右 1 从上往下 2 从右往左 3从下往上
	int  num = 1;//输入数组值  1---n*n
	int  gap = 0;//每行输出跨度 
	int i = 0, j = 0;//数组下标
	while (num <= n*n)//num自加到n*n时说明 全填满了 结束循环

	{
		if (type == 0)//从左向右 写入数组
		{
			for (int index = i + gap; i < n - gap&&num <= n*n; ++i)
				arr[i+j*n] = num++;
			++type;//横行写入数组完成 类型+1 变竖行
			++j;//j+1到下一行
		}
		if (type ==1)//从上到下
		{
			--i;//i退到 最外层处
			for (int index = j + gap; j< n - gap&&num <= n*n; ++j)
				arr[i + j*n] = num++;
			++type;
			--i; //i退到最外层-1处
		}
		if (type == 2)//从右到左
		{
			--j;//j退到未写入最外层
			for (int index = i - gap; i >= gap&&num <= n*n; --i)
				arr[i + j*n] = num++;
			++type;
			++i;//i到左边未遍历最外层
		}
		if (type == 3)//从下道上
		{
			--j;//j退到未写入最外层
			for (int index = n - gap; j > gap&&num <= n*n; --j)
				arr[i + j*n] = num++;
			++j;//j退到未写入最外层
			++i;//i到左边未遍历最外层
			type = 0;//写入方向 类型 重新置1
		}
		gap++;//四个方向 都写入完成  跨度+1
		
	}
	for (int index = 0; index < n*n; ++index)
		cout << arr[index] << ' ';
	cout << endl;
	delete arr;
}

//在一个字符串中 删除多余字符后 找到最长的 回文字符串长度
//eg:abbedbba  结果 abbebba  
//逻辑庞大 十分复杂 网上好像有高端算法

int PlalindromeNum(char* str,int start,int end)
{
  	if (*str == 0)//判断 指针有效性
		return 0;
	int count = 0;//当前回文字符串的字符数
	int bigCnt = 1;//最大回文字符串字符数
	int right = end;//临界值
	while (start<end&&count!=2)//如果找到最后一个当前字符的匹配项 或者 字符串到尾 跳出循环 
	{							//start 与end为当前子串最两端一对相同字符
		for (int i = start + 1; i <=right; ++i)
		{
			if (str[i] == str[start])
			{
				end = i;
				count = 2;//有相同项 count为2
			}
		}
		if (count != 2)//没有相同项 跳到下个字符
			++start;
	}
	if (end - start>2)//递归 找一对相同字符中的其他相同字符数量
		count += PlalindromeNum(str, start + 1, end - 1);
	else if (end - start == 2)//当end-start相距为2 说明中间包含若干单独字符 count++
	{
		++count;
		
	}

	if (right -end>1)//如果临界值-end>1说明后面还有没有遍历的字符 
	{
		if (bigCnt < count)//则将count 保存  置0
			bigCnt = count;
		count = 0;
		count += PlalindromeNum(str, end+1 , right);//从子串开始继续递归找匹配字符
	}
	if (bigCnt < count)
		bigCnt = count;//始终保持bigCnt为最长回文子串的字符数
	return bigCnt;
}

////用递归实现n位的格雷码  //至今未想明白
//
//char* Gray(int n)
//{
//	char *arry = (char*)malloc(sizeof(char)*(int)pow(2, n)+1);
//	if (n =1)
//	{
//		arry[0] = '0';
//		arry[1] = '1';
//		arry[2] =0 ;
//		return arry ;
//	}
//		
//	char * tmp=Gray(n - 1);
//	int j = (int)pow(2, n) - 2;
//	for (int i = 0;i<j; ++i)
//	{		
//		arry[i] = tmp[i] + 0;
//		arry[j - 1 - i] = tmp[i] + 1;
//	}
//	return arry;
//}
//

//有一串珠子2种颜色(红,蓝),n个(n为奇数),有多少个蓝珠子才能确定无论什么顺序穿
//都能从不同位置的两个蓝珠子
//截断为2串,并得到一串数量为(n+1)/2(不包括这两个蓝色珠子)

//重在逻辑理解 代码简单

void pearl_num(int n)
{
	if (n < 3 || n % 2 != 1)
		return;
	int head = 0,end=0,count=0,num=2;
	for (int i = 1; i <n-2; )
	{	
		end = i;
		if (end == (n + 1) / 2)
		{
			printf("%d\n", num);
			return;
		}
		if ((end - head - 1) == (n + 1) / 2 || (n - 1 - end) == (n + 1) / 2)
		{
			i++;
		}
		else if (count > 0)
		{
			count--;
			i++;
		}
		else
		{
			num++;
			count=num-2;
			i = 1;
		}
	}
	printf("无答案!\n");
}

//数字的汉子读法 0<=num<1000 例如 输入 101 输出yibailingyi 
void test()
{
	int num = 0;
	char* a[12] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu", "shi", "bai" };

	while (1)
	{
		int arr[3] = { 0 };
		char* pinyin = ((char*)malloc(sizeof(char)*20));
		scanf("%d", &num);
		int tmp1 = num;
		for (int i = 2; i >= 0; --i)
		{
			arr[i] = num % 10;
			num /= 10;
		}
		char* tmp = pinyin;
		for (int i = 0; i<3; ++i)
		{
			if (tmp1 == 0)
			{
				strcpy(pinyin, "ling\0");
				pinyin += 4;
				break;
			}
			if (i == 0)
			{
				if (arr[i] != 0)
				{
					strcpy(pinyin, a[arr[i]]);
					pinyin += (int)strlen(a[arr[i]]);
					strcpy(pinyin, a[11]);
					pinyin += 3;
				}
			}
			else if (i == 1)
			{
				if (arr[i] == 0)
				{
					if (arr[i - 1] == 0)
						continue;
					if (arr[i + 1] == 0)
						break;
					strcpy(pinyin, a[0]);
					pinyin += 4;
				}
				else
				{
					strcpy(pinyin, a[arr[i]]);
					pinyin += (int)strlen(a[arr[i]]);
					strcpy(pinyin, a[10]);
					pinyin += 3;
				}
			}
			else
			{
				if (arr[i] != 0)
				{
					strcpy(pinyin, a[arr[i]]);
					pinyin += (int)strlen(a[arr[i]]);

				}
			}
			free(pinyin);
		}
			*pinyin = 0;
			printf("%s\n", tmp);
			pinyin = tmp;
	}
}

//小明装装备按从左到右装  如果物品太大 (大于背包最大容量)直接丢弃,如果背包装不下  
//换下个背包,前一个背包不再用,小明能装多少物品?
//n 物品数 t 背包负重  m 背包个数
//a[0]--a[n]被给物品质量
//

void package()
{
	int m, t ,n;
	int a[20] = { 0 };
	int i = 0;
	scanf("%d%d%d",&n,&t,&m);
	while (i < n)
	{
		scanf("%d", &a[i++]);
	}
	int count = 0, tmp = t;

	for (i=0; m>0 && n > 0;)
	{
		if (a[i] > tmp)
		{
			i++;
			n++;
		}
		else if (t-a[i]>=0)
		{
			t -= a[i++];
			++count;
			--n;
		}
		else if (m>1)
		{
			--m;
			t = tmp;
			t -= a[i++];
			++count;
			--n;
	    }
		else
		{
			++i;
			--n;
		}
	}
	printf("%d\n",count);
}

//将字符串 按空格 翻转 同时 将大小写互换 例:“this Is a Str”-> "sTR A iS THIS"
//默认给定字符串只含有字母与空格

void reverse_str_A(char * src)
{
	char* str = (char*)malloc(sizeof(char)*(strlen(src)));//将给定字符串拷贝到可写字符数组中
	strcpy(str,src);
	char* tmp = str;
	int i = 0;
	char* out = (char*)malloc(sizeof(char)*(strlen(str) ));//生成储存处理后的字符数组
	char* output = out;
	while (*(tmp))//计算空格个数
	{
		if (*tmp++ == ' '&&*tmp!=0)//'\0'之前的不计算
			++i;
	}
	int count = i;
	int *a = (int *)malloc(sizeof(int)*i);//生成记录空格下标的数组
	tmp = str;
	i = 0;
	int j = 0;
	while (*tmp)//将空格下标记录并替换为'\0'方便拷贝
	{
		if (*tmp == ' ')//
		{
			*tmp = 0;
			if (*(tmp + 1)== 0)//'\0'之前的空格直接处理  将输出数组第一个字符替换为空格 并指向下一个
			{
				*output = ' ';
				output++;
				break;
			}
			a[j++] = i;
		}
		++tmp;
		++i;
	}
	tmp = str;
	for ( j = count-1; j>=0; --j)//将分割的字符串从后向前依次写入输出字符串并将各自\0替换为空格
	{
		if (a[0] == 0&&j==0)
			break;
		strcpy(output,tmp+a[j]+1);
		output += strlen(tmp + a[j]+1);
		*(output++) = ' ';
	}
	if (a[0] == 0)//处理开始空格
		tmp++;
	strcpy(output, tmp );//将首字符串拷贝到尾
	output += strlen(tmp );
	if (a[0] == 0)//将开始的空格移到末尾
	{
		output[0]= ' ';
		output[1] = 0;
	}
	i = 0;
	output = out;
	while (*(output+i))//依次替换大小写
	{
		if (*(output + i) >= 'a'&&*(output + i) <= 'z')
			*(output + i) -= 32;
		else if (*(output + i) >= 'A'&&*(output + i) <= 'Z')
			*(output + i) += 32;
		++i;
	}		
	cout << out <<"***********"<< endl;//输出
	free(out);
	free(output);
	free(a);
}

int main()
{
	cout<<CowNum(20)<<endl;
	cout << CowNum1(20) << endl;
	AllColorBead("11231324566457711234567111", 7);
	AllColorBead("asdccaacsdfdgfwererdfg",8);

	SnakeArr(5);
	char* a = "vvaabbcdcbbaaxaabbcdcbbaax";
	cout << PlalindromeNum(a, 0, strlen(a)) << endl;

	/*pearl_num(101);
	package();*/
	reverse_str_A("        This   w W w  Is str ");
	/*test();*/

	/*char * aa;
	 aa=Gray(10);
	 cout << aa << endl;*/
	return 0;
}